{
  "openapi": "3.1.0",
  "info": {
    "title": "Everyday Public API",
    "version": "1.1.0",
    "description": "Public developer API for the Everyday platform.",
    "contact": {
      "name": "Everyday Developer Support",
      "email": "developers@every.day",
      "url": "https://every.day/"
    },
    "license": {
      "name": "MIT",
      "url": "https://opensource.org/licenses/MIT"
    }
  },
  "tags": [
    {
      "name": "Organizations",
      "description": "Organizations available to the authenticated caller for profile creation."
    },
    {
      "name": "Profiles",
      "description": "Public-facing profiles owned by Everyday users. Each profile groups events, series, and followers under a single identity."
    },
    {
      "name": "Events",
      "description": "Individual scheduled events with start times, RSVPs, and optional recurrence."
    },
    {
      "name": "RSVPs",
      "description": "Per-event attendee responses and RSVP capacity/notification settings."
    },
    {
      "name": "Series",
      "description": "Ordered or themed collections of events under a profile (e.g., a season, a course, a tour)."
    },
    {
      "name": "Calendars",
      "description": "User-owned calendars and the events placed on them. Distinct from public profile events; these are the user's personal schedule."
    },
    {
      "name": "Subscriptions",
      "description": "Follow-style subscriptions that sync a profile or series into a user's calendar."
    },
    {
      "name": "Follows",
      "description": "Lightweight follow relationships between users and profiles, series, or events."
    },
    {
      "name": "Search",
      "description": "Cross-resource search across events, profiles, and series."
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol endpoints exposing the API as MCP tools. /mcp authenticates via OAuth (consumer-facing); /mcp-developer authenticates via API key."
    }
  ],
  "servers": [
    {
      "url": "https://api.every.day"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Everyday API key. Send as `Authorization: Bearer <key>`."
      }
    },
    "parameters": {
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Opaque cursor returned from a previous list response."
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        },
        "description": "Maximum number of items to return per page. Range 1-100, default 20."
      },
      "Expand": {
        "name": "expand",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Comma-separated list of relationships to expand inline in the response. Max 3 expansions, depth 1."
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 255
        },
        "description": "A client-generated identifier (UUIDv4 recommended; 8–255 chars, alphanumeric/underscore/hyphen) for the request. The header is validated and logged, but server-side deduplication is **not** enforced: resubmitting a create with the same key produces a second resource. Treat creates as non-idempotent and design retries accordingly. Deduplication is planned for a future API version."
      },
      "ProfileId": {
        "name": "profile_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^prf_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the profile (e.g., `prf_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "EventId": {
        "name": "event_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^evt_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the event (e.g., `evt_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "RsvpId": {
        "name": "rsvp_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^rsvp_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the RSVP (e.g., `rsvp_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "SeriesId": {
        "name": "series_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^ser_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the series (e.g., `ser_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "CalendarId": {
        "name": "calendar_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^cal_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the calendar (e.g., `cal_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "SubscriptionId": {
        "name": "subscription_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^sub_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the subscription (e.g., `sub_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "FollowId": {
        "name": "follow_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^fol_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the follow (e.g., `fol_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      },
      "CalendarEventId": {
        "name": "event_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^cev_[0-9a-fA-F]{32}$"
        },
        "description": "Prefixed unique identifier of the calendar event (e.g., `cev_8f3ab21e49c44c8baf7b5e4a1b2c3d4e`)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "permission_error",
                  "not_found_error",
                  "rate_limit_error",
                  "conflict_error",
                  "api_error",
                  "service_unavailable"
                ]
              },
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code (e.g., `not_authenticated`, `consumer_not_claimed`, `forbidden`, `resource_not_found`, `conflict`, `rate_limit_exceeded`). Code values are stable across API versions; rely on these rather than parsing `message`."
              },
              "message": {
                "type": "string",
                "description": "Human-readable description of the error. Subject to wording changes — do not match on substring."
              },
              "param": {
                "type": "string",
                "description": "When the error is caused by a specific request parameter, the name of that parameter."
              },
              "request_id": {
                "type": "string",
                "description": "Unique identifier for this request. Include this value when reaching out to support; it lets us locate the exact request in our logs."
              },
              "details": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "value": {
                    "type": "string"
                  },
                  "expected_offset": {
                    "type": "string"
                  },
                  "gap_from": {
                    "type": "string"
                  },
                  "gap_to": {
                    "type": "string"
                  },
                  "start": {
                    "type": "string"
                  },
                  "end": {
                    "type": "string"
                  },
                  "expected_shapes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "valid_offsets": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "Profile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "prf_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "pattern": "^prf_[0-9a-fA-F]{32}$"
          },
          "everyday_id": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.-]{3,}$",
            "description": "Profile handle used in links. This is not a resource ID; use the profile id (prf_...) in ID fields."
          },
          "display_name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "header_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_private": {
            "type": "boolean"
          },
          "default_event_duration_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "ProfileCreate": {
        "type": "object",
        "required": [
          "everyday_id",
          "display_name"
        ],
        "properties": {
          "everyday_id": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.-]{3,}$",
            "description": "Profile handle used in links. This is not a resource ID; use the profile id (prf_...) in ID fields."
          },
          "display_name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "header_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_private": {
            "type": "boolean"
          },
          "organization_id": {
            "type": "string",
            "pattern": "^org_[0-9a-fA-F]{32}$",
            "description": "Optional organization from GET /v1/organizations. When omitted, the caller's single active owned organization is used."
          }
        },
        "additionalProperties": false
      },
      "ProfileUpdate": {
        "type": "object",
        "properties": {
          "display_name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "header_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_private": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "evt_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "pattern": "^evt_[0-9a-fA-F]{32}$"
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^prf_[0-9a-fA-F]{32}$",
            "example": "prf_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "description": "Owning profile ID. Null when the profile is no longer visible to the caller."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_time": {
            "type": "string",
            "format": "date-time"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "start_timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "end_timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "recurrence_rule": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "type": "string"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_all_day": {
            "type": "boolean"
          },
          "is_private": {
            "type": "boolean"
          },
          "require_rsvp": {
            "type": "boolean"
          },
          "require_payment": {
            "type": "boolean"
          },
          "cancellation_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "is_rescheduled": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "RFC 5545 busy/free behavior: opaque blocks time; transparent does not."
          }
        },
        "additionalProperties": false
      },
      "EventCreate": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "profile_id": {
            "type": "string",
            "description": "Required when calling POST /v1/events; inferred from path when calling POST /v1/profiles/{profile_id}/events.",
            "pattern": "^prf_[0-9a-fA-F]{32}$"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_time": {
            "type": "string",
            "description": "Event start time. Recommended: a naive local time (no offset) interpreted in start_timezone — e.g. \"2026-06-06T09:30:00\". An offset-bearing RFC 3339 value (e.g. \"2026-06-06T09:30:00-04:00\") is also accepted. Must be sent together with start_timezone. Omit for all-day events (use start_date).",
            "examples": [
              "2026-06-06T09:30:00",
              "2026-06-06T09:30:00-04:00"
            ],
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "description": "Event end time, same formats as start_time. When present, must be sent together with end_timezone. Omit for all-day events (use end_date).",
            "examples": [
              "2026-06-06T11:30:00",
              "2026-06-06T11:30:00-04:00"
            ],
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "start_timezone": {
            "type": "string",
            "description": "IANA timezone name (e.g. \"America/New_York\") for start_time. Required. Used for display, outbound calendar sync, and recurrence expansion; it does not reinterpret an explicit offset in start_time. Must not be null."
          },
          "end_timezone": {
            "type": "string",
            "description": "IANA timezone name for end_time. Independent of start_timezone (e.g. a NYC→LA flight). Must be sent together with end_time and must not be null. When omitted on create, the platform fills it from start_timezone."
          },
          "start_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day start date (YYYY-MM-DD, date only). Required when is_all_day is true; do not send with start_time/end_time."
          },
          "end_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day end date (YYYY-MM-DD), EXCLUSIVE — the event spans up to but not including this date. Optional; defaults to start_date + 1 day (single day) and must be after start_date (multi-day allowed)."
          },
          "recurrence_rule": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 8192,
            "description": "Single RRULE text (optional RRULE: prefix), or null to clear recurrence. Must produce a first occurrence within a bounded work allowance using the effective event start. Invalid or excessively costly rules return 400 invalid_recurrence_rule. Advanced rules such as BYDAY=2TU are supported."
          },
          "slug": {
            "type": "string",
            "description": "URL slug for the event. Optional — when omitted the platform derives one from the title and start time (evaluated in start_timezone). Reserved values (history, previous, s) are rejected."
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_all_day": {
            "type": "boolean"
          },
          "is_private": {
            "type": "boolean"
          },
          "require_rsvp": {
            "type": "boolean"
          },
          "require_payment": {
            "type": "boolean"
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "RFC 5545 busy/free behavior: opaque blocks time; transparent does not."
          }
        },
        "if": {
          "properties": {
            "is_all_day": {
              "const": true
            }
          },
          "required": [
            "is_all_day"
          ]
        },
        "then": {
          "required": [
            "start_date",
            "start_timezone"
          ]
        },
        "else": {
          "required": [
            "start_time",
            "start_timezone"
          ],
          "dependentRequired": {
            "start_time": [
              "start_timezone"
            ],
            "start_timezone": [
              "start_time"
            ],
            "end_time": [
              "end_timezone"
            ],
            "end_timezone": [
              "end_time"
            ]
          }
        },
        "additionalProperties": false
      },
      "EventUpdate": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_time": {
            "type": "string",
            "description": "Event start as an RFC 3339 date-time. When present, must be sent together with start_timezone.",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "description": "Event end as an RFC 3339 date-time. When present, must be sent together with end_timezone.",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "start_timezone": {
            "type": "string",
            "description": "IANA timezone name for start_time. Required when start_time is present (they must travel together). Used for display, outbound calendar sync, and recurrence expansion. Must not be null. Omit to leave unchanged."
          },
          "end_timezone": {
            "type": "string",
            "description": "IANA timezone name for end_time. Independent of start_timezone. Required when end_time is present. Must not be null. Omit to leave unchanged; no cascade from a start_timezone change."
          },
          "start_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day start date (YYYY-MM-DD, date only). Required when is_all_day is true; do not send with start_time/end_time."
          },
          "end_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day end date (YYYY-MM-DD), EXCLUSIVE — the event spans up to but not including this date. Optional; defaults to start_date + 1 day (single day) and must be after start_date (multi-day allowed)."
          },
          "recurrence_rule": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 8192,
            "description": "Single RRULE text (optional RRULE: prefix), or null to clear recurrence. Must produce a first occurrence within a bounded work allowance using the effective event start. Invalid or excessively costly rules return 400 invalid_recurrence_rule. Advanced rules such as BYDAY=2TU are supported."
          },
          "slug": {
            "type": "string"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_all_day": {
            "type": "boolean"
          },
          "is_private": {
            "type": "boolean"
          },
          "require_rsvp": {
            "type": "boolean"
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "RFC 5545 busy/free behavior: opaque blocks time; transparent does not."
          }
        },
        "dependentRequired": {
          "start_time": [
            "start_timezone"
          ],
          "start_timezone": [
            "start_time"
          ],
          "end_time": [
            "end_timezone"
          ],
          "end_timezone": [
            "end_time"
          ]
        },
        "additionalProperties": false
      },
      "EventCancel": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "EventReschedule": {
        "type": "object",
        "required": [
          "start_time"
        ],
        "properties": {
          "start_time": {
            "type": "string",
            "description": "New event start as an RFC 3339 date-time. Must be sent together with start_timezone.",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "end_time": {
            "type": "string",
            "description": "New event end as an RFC 3339 date-time. When present, must be sent together with end_timezone.",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "start_timezone": {
            "type": "string",
            "description": "IANA timezone name for the new start_time. Required (reschedule always sets start_time). Must not be null."
          },
          "end_timezone": {
            "type": "string",
            "description": "IANA timezone name for the new end_time. Independent of start_timezone. Required when end_time is present. Must not be null."
          }
        },
        "dependentRequired": {
          "start_time": [
            "start_timezone"
          ],
          "start_timezone": [
            "start_time"
          ],
          "end_time": [
            "end_timezone"
          ],
          "end_timezone": [
            "end_time"
          ]
        },
        "additionalProperties": false
      },
      "Series": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "ser_...",
            "pattern": "^ser_[0-9a-fA-F]{32}$"
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^prf_[0-9a-fA-F]{32}$",
            "example": "prf_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "description": "Owning profile ID. Null when the profile is no longer visible to the caller."
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_private": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "SeriesCreate": {
        "type": "object",
        "required": [
          "name",
          "slug"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_private": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "SeriesUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_private": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Rsvp": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "rsvp_...",
            "pattern": "^rsvp_[0-9a-fA-F]{32}$"
          },
          "event_id": {
            "type": "string",
            "pattern": "^evt_[0-9a-fA-F]{32}$",
            "example": "evt_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "description": "Event containing this RSVP."
          },
          "attendee_email": {
            "type": [
              "string",
              "null"
            ]
          },
          "attendee_first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "attendee_last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "rsvp_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "num_guests": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "RsvpCreate": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "attendee_email": {
            "type": [
              "string",
              "null"
            ]
          },
          "attendee_first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "attendee_last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "going",
              "maybe",
              "not_going",
              "waitlist"
            ]
          },
          "rsvp_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "num_guests": {
            "type": "integer",
            "minimum": 1,
            "default": 1
          }
        },
        "additionalProperties": false
      },
      "RsvpUpdate": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "going",
              "maybe",
              "not_going",
              "waitlist"
            ]
          },
          "num_guests": {
            "type": "integer",
            "minimum": 1
          }
        },
        "additionalProperties": false
      },
      "RsvpStats": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "pattern": "^evt_[0-9a-fA-F]{32}$"
          },
          "going": {
            "type": "integer"
          },
          "maybe": {
            "type": "integer"
          },
          "not_going": {
            "type": "integer"
          },
          "waitlist": {
            "type": "integer"
          },
          "total_attendees": {
            "type": "integer"
          }
        },
        "additionalProperties": false
      },
      "RsvpSettings": {
        "type": "object",
        "properties": {
          "enable_capacity_limit": {
            "type": "boolean"
          },
          "capacity_limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "allow_waitlist": {
            "type": "boolean"
          },
          "allow_multiple_attendees": {
            "type": "boolean"
          },
          "allow_notifications": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "RsvpSettingsUpdate": {
        "type": "object",
        "properties": {
          "enable_capacity_limit": {
            "type": "boolean"
          },
          "capacity_limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "allow_waitlist": {
            "type": "boolean"
          },
          "allow_multiple_attendees": {
            "type": "boolean"
          },
          "allow_notifications": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Calendar": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cal_...",
            "pattern": "^cal_[0-9a-fA-F]{32}$"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "color": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_default": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "CalendarEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "cev_...",
            "pattern": "^cev_[0-9a-fA-F]{32}$"
          },
          "calendar_id": {
            "type": "string",
            "pattern": "^cal_[0-9a-fA-F]{32}$",
            "example": "cal_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "description": "Personal calendar containing this event."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_time": {
            "type": "string",
            "format": "date-time"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "start_timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "end_timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_all_day": {
            "type": "boolean"
          },
          "recurrence_rule": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "RFC 5545 busy/free behavior: opaque blocks time; transparent does not."
          }
        },
        "additionalProperties": false
      },
      "CalendarEventCreate": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_time": {
            "type": "string",
            "description": "Event start time. Recommended: a naive local time (no offset) interpreted in start_timezone — e.g. \"2026-06-06T09:30:00\". An offset-bearing RFC 3339 value is also accepted. Must be sent together with start_timezone. Omit for all-day events (use start_date).",
            "examples": [
              "2026-06-06T09:30:00",
              "2026-06-06T09:30:00-04:00"
            ],
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "description": "Event end time, same formats as start_time. When present, must be sent together with end_timezone. Omit for all-day events (use end_date).",
            "examples": [
              "2026-06-06T11:30:00",
              "2026-06-06T11:30:00-04:00"
            ],
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "start_timezone": {
            "type": "string",
            "description": "IANA timezone name for start_time. Required. Used for display and recurrence; not used to reinterpret an explicit offset. Must not be null."
          },
          "end_timezone": {
            "type": "string",
            "description": "IANA timezone name for end_time. Independent of start_timezone. Required when end_time is present. Must not be null."
          },
          "start_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day start date (YYYY-MM-DD, date only). Required when is_all_day is true; do not send with start_time/end_time."
          },
          "end_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day end date (YYYY-MM-DD), EXCLUSIVE. Optional; defaults to start_date + 1 day (single day) and must be after start_date (multi-day allowed)."
          },
          "is_all_day": {
            "type": "boolean"
          },
          "recurrence_rule": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 8192,
            "description": "Single RRULE text (optional RRULE: prefix), or null to clear recurrence. Must produce a first occurrence within a bounded work allowance using the effective event start. Invalid or excessively costly rules return 400 invalid_recurrence_rule. Advanced rules such as BYDAY=2TU are supported."
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "RFC 5545 busy/free behavior: opaque blocks time; transparent does not."
          }
        },
        "if": {
          "properties": {
            "is_all_day": {
              "const": true
            }
          },
          "required": [
            "is_all_day"
          ]
        },
        "then": {
          "required": [
            "start_date",
            "start_timezone"
          ]
        },
        "else": {
          "required": [
            "start_time",
            "start_timezone"
          ],
          "dependentRequired": {
            "start_time": [
              "start_timezone"
            ],
            "start_timezone": [
              "start_time"
            ],
            "end_time": [
              "end_timezone"
            ],
            "end_timezone": [
              "end_time"
            ]
          }
        },
        "additionalProperties": false
      },
      "CalendarEventUpdate": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "start_time": {
            "type": "string",
            "description": "Event start time (naive local + start_timezone recommended; offset-bearing also accepted). When present, must be sent together with start_timezone.",
            "examples": [
              "2026-06-06T09:30:00",
              "2026-06-06T09:30:00-04:00"
            ],
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "description": "Event end time, same formats as start_time. When present, must be sent together with end_timezone. Omit for all-day events (use end_date).",
            "examples": [
              "2026-06-06T11:30:00",
              "2026-06-06T11:30:00-04:00"
            ],
            "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?$"
          },
          "start_timezone": {
            "type": "string",
            "description": "IANA timezone name for start_time. Required when start_time is present. Used for display and recurrence; not used to reinterpret an explicit offset. Must not be null."
          },
          "end_timezone": {
            "type": "string",
            "description": "IANA timezone name for end_time. Independent of start_timezone. Required when end_time is present. Must not be null."
          },
          "start_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day start date (YYYY-MM-DD, date only). Required when is_all_day is true; do not send with start_time/end_time."
          },
          "end_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "All-day end date (YYYY-MM-DD), EXCLUSIVE. Optional; defaults to start_date + 1 day (single day) and must be after start_date (multi-day allowed)."
          },
          "is_all_day": {
            "type": "boolean"
          },
          "recurrence_rule": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 8192,
            "description": "Single RRULE text (optional RRULE: prefix), or null to clear recurrence. Must produce a first occurrence within a bounded work allowance using the effective event start. Invalid or excessively costly rules return 400 invalid_recurrence_rule. Advanced rules such as BYDAY=2TU are supported."
          },
          "transparency": {
            "type": "string",
            "enum": [
              "opaque",
              "transparent"
            ],
            "description": "RFC 5545 busy/free behavior: opaque blocks time; transparent does not."
          }
        },
        "dependentRequired": {
          "start_time": [
            "start_timezone"
          ],
          "start_timezone": [
            "start_time"
          ],
          "end_time": [
            "end_timezone"
          ],
          "end_timezone": [
            "end_time"
          ]
        },
        "additionalProperties": false
      },
      "Subscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "sub_...",
            "pattern": "^sub_[0-9a-fA-F]{32}$"
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^prf_[0-9a-fA-F]{32}$",
            "example": "prf_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "description": "Profile source for a profile subscription; otherwise null. A null value for a profile subscription means the source is no longer visible. Use subscription_type to identify the source type."
          },
          "series_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^ser_[0-9a-fA-F]{32}$",
            "example": "ser_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "description": "Series source for a series subscription; otherwise null. A null value for a series subscription means the source is no longer visible. Use subscription_type to identify the source type."
          },
          "subscription_type": {
            "type": "string"
          },
          "is_active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "access_valid": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "include_personal_calendar": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "SubscriptionCreate": {
        "type": "object",
        "required": [
          "subscription_type"
        ],
        "properties": {
          "subscription_type": {
            "type": "string",
            "enum": [
              "profile",
              "series"
            ]
          },
          "profile_id": {
            "type": "string",
            "pattern": "^prf_[0-9a-fA-F]{32}$"
          },
          "series_id": {
            "type": "string",
            "pattern": "^ser_[0-9a-fA-F]{32}$"
          },
          "include_personal_calendar": {
            "type": "boolean"
          },
          "external_calendar_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^xcal_[0-9a-fA-F]{32}$"
            },
            "maxItems": 100,
            "uniqueItems": true,
            "description": "Connected external calendars returned by GET /v1/external-calendars. Personal cal_ IDs are not accepted. Omission means no external targets; personal calendar inclusion defaults to true."
          },
          "consolidate": {
            "type": "boolean",
            "default": false,
            "description": "Explicitly adopt matching manual/child-series sync intent into this subscription. Defaults to false. May retire redundant child subscriptions."
          }
        },
        "additionalProperties": false
      },
      "SubscriptionUpdate": {
        "type": "object",
        "properties": {
          "is_active": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Follow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "fol_...",
            "pattern": "^fol_[0-9a-fA-F]{32}$"
          },
          "following_type": {
            "type": "string",
            "enum": [
              "profile",
              "series",
              "event"
            ]
          },
          "target_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(prf|ser|evt)_[0-9a-fA-F]{32}$",
            "description": "Prefixed identifier of the followed profile, series, or event. Null only when the original target is no longer visible."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "FollowCreate": {
        "type": "object",
        "required": [
          "following_type",
          "target_id"
        ],
        "properties": {
          "following_type": {
            "type": "string",
            "enum": [
              "profile",
              "series",
              "event"
            ]
          },
          "target_id": {
            "type": "string",
            "description": "Prefixed ID of the target resource.",
            "pattern": "^(prf|ser|evt)_[0-9a-fA-F]{32}$"
          }
        },
        "additionalProperties": false
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchItem"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ]
          },
          "id": {
            "description": "Request id echoed from the JSON-RPC request. May be a string, integer, or null.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "result": {
            "type": "object",
            "description": "Method-specific result payload. Present on successful responses; mutually exclusive with `error`."
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "description": "Present on failed responses; mutually exclusive with `result`.",
            "properties": {
              "code": {
                "type": "integer",
                "description": "JSON-RPC error code (e.g., -32601 for method not found)."
              },
              "message": {
                "type": "string"
              },
              "data": {
                "description": "Optional method-specific error data."
              }
            }
          }
        },
        "additionalProperties": false
      },
      "FollowPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Follow"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "SeriesPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Series"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "SubscriptionPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Subscription"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "ProfilePage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Profile"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "CalendarEventPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CalendarEvent"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "EventPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "CalendarPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Calendar"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "RsvpPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rsvp"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "SeriesDeletion": {
        "type": "object",
        "required": [
          "member_count",
          "deleted_event_count",
          "preserved_event_count"
        ],
        "properties": {
          "member_count": {
            "type": "integer",
            "description": "Total events that were tagged in this series at delete time."
          },
          "deleted_event_count": {
            "type": "integer",
            "description": "Events permanently deleted (only nonzero when cascade_exclusive_events=true)."
          },
          "preserved_event_count": {
            "type": "integer",
            "description": "Events that remain on the profile after deletion."
          }
        },
        "additionalProperties": false
      },
      "SeriesDeletionPreview": {
        "type": "object",
        "required": [
          "series_name",
          "member_count",
          "exclusive_count",
          "shared_count",
          "member_recurring_count",
          "exclusive_recurring_count",
          "shared_recurring_count"
        ],
        "properties": {
          "series_name": {
            "type": "string"
          },
          "member_count": {
            "type": "integer",
            "description": "Total events tagged in this series."
          },
          "exclusive_count": {
            "type": "integer",
            "description": "Events that would be deleted in cascade mode."
          },
          "shared_count": {
            "type": "integer",
            "description": "Events that would be preserved (also tagged in other series)."
          },
          "member_recurring_count": {
            "type": "integer",
            "minimum": 0
          },
          "exclusive_recurring_count": {
            "type": "integer",
            "minimum": 0
          },
          "shared_recurring_count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "additionalProperties": false
      },
      "SeriesAddEvent": {
        "type": "object",
        "required": [
          "event_id"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "pattern": "^evt_[0-9a-fA-F]{32}$"
          }
        },
        "additionalProperties": false
      },
      "SearchItem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "event",
              "profile",
              "series"
            ]
          },
          "id": {
            "type": "string",
            "pattern": "^(evt|prf|ser)_[0-9a-fA-F]{32}$"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "rank": {
            "type": [
              "number",
              "null"
            ]
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_handle": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Za-z0-9_.-]{3,}$"
          },
          "date_info": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ClaimConsumer": {
        "type": "object",
        "required": [
          "consumerName"
        ],
        "properties": {
          "consumerName": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$",
            "description": "Zuplo consumer name (request.user.sub on monetized routes)."
          }
        },
        "additionalProperties": false
      },
      "ExternalCalendar": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^xcal_[0-9a-fA-F]{32}$"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "color": {
            "type": [
              "string",
              "null"
            ]
          },
          "can_edit": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "time_zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_primary": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ExternalCalendarPage": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalCalendar"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false
      },
      "Organization": {
        "type": "object",
        "required": [
          "id",
          "name",
          "handle",
          "role",
          "is_default"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^org_[0-9a-fA-F]{32}$",
            "description": "Public organization ID accepted by profile creation."
          },
          "name": {
            "type": "string"
          },
          "handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string",
            "description": "The authenticated caller's role in this organization."
          },
          "is_default": {
            "type": "boolean",
            "description": "True only when this is the caller's single active owned organization and will be used when profile creation omits organization_id."
          }
        },
        "additionalProperties": false
      },
      "OrganizationList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Organization"
            }
          }
        },
        "additionalProperties": false
      },
      "ProfileCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "prf_8f3ab21e49c44c8baf7b5e4a1b2c3d4e",
            "pattern": "^prf_[0-9a-fA-F]{32}$"
          },
          "everyday_id": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.-]{3,}$",
            "description": "Profile handle used in links. This is not a resource ID; use the profile id (prf_...) in ID fields."
          },
          "display_name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "header_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "is_private": {
            "type": "boolean"
          },
          "default_event_duration_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "organization_id": {
            "type": "string",
            "pattern": "^org_[0-9a-fA-F]{32}$",
            "description": "The organization selected explicitly or resolved from the caller's owned default."
          }
        },
        "additionalProperties": false,
        "required": [
          "organization_id"
        ]
      },
      "AgendaWindow": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "type": "string"
          },
          "start": {
            "type": "string",
            "format": "date-time"
          },
          "end": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "date",
          "end_date",
          "timezone",
          "start",
          "end"
        ]
      },
      "AgendaSource": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "calendar_id": {
            "type": "string",
            "pattern": "^(?:cal|xcal)_[0-9a-fA-F]{32}$"
          },
          "name": {
            "type": "string"
          },
          "provider": {
            "type": "string",
            "enum": [
              "everyday",
              "google",
              "microsoft",
              "ios"
            ]
          },
          "last_sync_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "warning"
            ]
          }
        },
        "required": [
          "calendar_id",
          "name",
          "provider",
          "last_sync_at",
          "status"
        ]
      },
      "AgendaItem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "occurrence_id": {
            "type": "string",
            "description": "Identifies this occurrence using the event ID and original slot. No write endpoint accepts it."
          },
          "calendar_id": {
            "type": "string",
            "pattern": "^(?:cal|xcal)_[0-9a-fA-F]{32}$"
          },
          "event_id": {
            "type": "string",
            "pattern": "^(?:cev|xcev)_[0-9a-fA-F]{32}$",
            "description": "xcev_ IDs are read-only and stable while the stored row exists. Removing and reimporting an event may assign a new ID."
          },
          "editable": {
            "type": "boolean",
            "description": "True only for non-recurring personal events, editable through the calendar-event PATCH route."
          },
          "title": {
            "type": "string"
          },
          "start": {
            "type": "string",
            "format": "date-time"
          },
          "end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "local_start": {
            "type": "string",
            "format": "date-time"
          },
          "local_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "is_all_day": {
            "type": "boolean"
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "All-day events only; authoritative calendar date."
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "All-day events only; exclusive end date."
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "provider": {
                "type": "string",
                "enum": [
                  "everyday",
                  "google",
                  "microsoft",
                  "ios"
                ]
              },
              "calendar_name": {
                "type": "string"
              }
            },
            "required": [
              "provider",
              "calendar_name"
            ]
          },
          "busy": {
            "type": "boolean"
          },
          "is_recurring": {
            "type": "boolean"
          },
          "profile": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^(?:prf)_[0-9a-fA-F]{32}$"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Present only with detail=full."
          }
        },
        "required": [
          "occurrence_id",
          "calendar_id",
          "event_id",
          "editable",
          "title",
          "start",
          "end",
          "local_start",
          "local_end",
          "is_all_day",
          "location",
          "source",
          "busy",
          "is_recurring",
          "profile"
        ]
      },
      "Agenda": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "window": {
            "$ref": "#/components/schemas/AgendaWindow"
          },
          "data": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "$ref": "#/components/schemas/AgendaItem"
            }
          },
          "complete": {
            "type": "boolean",
            "description": "Whether the query and expansion returned all matching stored data. Does not guarantee provider coverage or freshness."
          },
          "incomplete_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgendaSource"
            }
          }
        },
        "required": [
          "window",
          "data",
          "complete",
          "incomplete_reason",
          "sources"
        ]
      }
    },
    "responses": {
      "Error": {
        "description": "Generic error response. Used as the `default` fallback on most operations.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The request did not include a valid API key (or, on OAuth-protected routes, a valid bearer token). Send `Authorization: Bearer <key>`.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "not_authenticated",
                "message": "Authentication required.",
                "request_id": "req_8f3ab21e49c44c8baf7b5e4a1b2c3d4e"
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The authenticated principal does not have permission to perform this action on the requested resource.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "permission_error",
                "code": "forbidden",
                "message": "Not permitted.",
                "request_id": "req_8f3ab21e49c44c8baf7b5e4a1b2c3d4e"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested resource does not exist, or is not visible to the authenticated principal. Visibility-based filtering returns 404 (not 403) by design to avoid leaking the existence of private resources.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "not_found_error",
                "code": "resource_not_found",
                "message": "Resource not found.",
                "request_id": "req_8f3ab21e49c44c8baf7b5e4a1b2c3d4e"
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "The request conflicts with the current state of the server. Typically returned when a uniqueness constraint is violated (for example, creating a profile with an `everyday_id` already in use).",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "conflict_error",
                "code": "conflict",
                "message": "Resource conflict.",
                "request_id": "req_8f3ab21e49c44c8baf7b5e4a1b2c3d4e"
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded. Inspect the `Retry-After` header for the recommended wait time before retrying.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
                "message": "Too many requests.",
                "request_id": "req_8f3ab21e49c44c8baf7b5e4a1b2c3d4e"
              }
            }
          }
        }
      },
      "InternalServerError": {
        "description": "The server encountered an unexpected condition that prevented it from completing the request. Retries are safe for `GET`, `PUT`, and `DELETE` requests; include the `request_id` from the response body when reporting persistent failures.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "api_error",
                "code": "internal_error",
                "message": "An error occurred processing this request.",
                "request_id": "req_8f3ab21e49c44c8baf7b5e4a1b2c3d4e"
              }
            }
          }
        }
      },
      "RateLimitNoRetryAfter": {
        "description": "Rate Limiting Response",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "type",
                "title",
                "status"
              ],
              "examples": [
                {
                  "type": "https://httpproblems.com/http-status/429",
                  "title": "Too Many Requests",
                  "status": 429,
                  "instance": "/foo/bar"
                }
              ],
              "properties": {
                "type": {
                  "type": "string",
                  "example": "https://httpproblems.com/http-status/429",
                  "description": "A URI reference that identifies the problem."
                },
                "title": {
                  "type": "string",
                  "example": "Too Many Requests",
                  "description": "A short, human-readable summary of the problem."
                },
                "status": {
                  "type": "number",
                  "example": 429,
                  "description": "The HTTP status code."
                },
                "instance": {
                  "type": "string",
                  "example": "/foo/bar"
                }
              }
            }
          }
        }
      },
      "RateLimitWithRetryAfter": {
        "description": "Rate Limiting Response",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "type",
                "title",
                "status"
              ],
              "examples": [
                {
                  "type": "https://httpproblems.com/http-status/429",
                  "title": "Too Many Requests",
                  "status": 429,
                  "instance": "/foo/bar"
                }
              ],
              "properties": {
                "type": {
                  "type": "string",
                  "example": "https://httpproblems.com/http-status/429",
                  "description": "A URI reference that identifies the problem."
                },
                "title": {
                  "type": "string",
                  "example": "Too Many Requests",
                  "description": "A short, human-readable summary of the problem."
                },
                "status": {
                  "type": "number",
                  "example": 429,
                  "description": "The HTTP status code."
                },
                "instance": {
                  "type": "string",
                  "example": "/foo/bar"
                }
              }
            }
          }
        },
        "headers": {
          "retry-after": {
            "description": "The number of seconds to wait before making a new request.",
            "schema": {
              "type": "integer",
              "example": 60
            }
          }
        }
      }
    },
    "headers": {
      "XRateLimitLimit": {
        "description": "Maximum number of requests permitted in the current rate-limit window.",
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitRemaining": {
        "description": "Number of requests remaining in the current rate-limit window.",
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitReset": {
        "description": "Unix epoch seconds at which the current rate-limit window resets.",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Number of seconds to wait before retrying. Present on 429 responses; may be present on 503 responses when service degradation is transient.",
        "schema": {
          "type": "integer"
        }
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/v1/profiles": {
      "get": {
        "summary": "List profiles",
        "description": "Returns the profiles the authenticated caller can manage — those they own directly or administer through an organization they belong to. This is a workflow endpoint, not platform-wide discovery: public profiles owned by others are not returned. Use it to resolve a name to a profile you can write to before creating or modifying its events or series. (Platform-wide public search is a separate, forthcoming capability.)",
        "operationId": "listProfiles",
        "tags": [
          "Profiles"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of profiles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfilePage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create profile",
        "description": "Creates a profile owned by the authenticated user. organization_id is optional when the caller has one active owned organization; use GET /v1/organizations to select another available organization. everyday_id must be unique across the platform; conflicts return 409.",
        "operationId": "createProfile",
        "tags": [
          "Profiles"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileCreated"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/profiles/{profile_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProfileId"
        }
      ],
      "get": {
        "summary": "Retrieve profile",
        "description": "Returns a single profile by its prefixed ID. Returns 404 if the profile does not exist or is private and not visible to the caller.",
        "operationId": "getProfile",
        "tags": [
          "Profiles"
        ],
        "responses": {
          "200": {
            "description": "Profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Profile"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "summary": "Update profile",
        "description": "Updates a profile owned by the authenticated user. Only the caller's own profiles are mutable; attempting to update someone else's profile returns 404.",
        "operationId": "updateProfile",
        "tags": [
          "Profiles"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Profile"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete profile",
        "description": "Soft-deletes a profile and schedules its associated data for cleanup. Idempotent — deleting an already-deleted profile is a no-op.",
        "operationId": "deleteProfile",
        "tags": [
          "Profiles"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/profiles/{profile_id}/events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProfileId"
        }
      ],
      "get": {
        "summary": "List a profile's events",
        "description": "Returns events belonging to the specified profile. Honors the same visibility rules as `listEvents` — private events on a private profile are not returned to non-owners.",
        "operationId": "listProfileEvents",
        "tags": [
          "Profiles",
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create event for a profile",
        "description": "Creates an event under a profile owned by the authenticated user. The `profile_id` is taken from the path; the request body must not also set it. Identical to `createEvent` except that the parent profile is path-bound. \n\nTime formats — timed events: send a naive local time plus a timezone (recommended), e.g. start_time \"2026-06-06T09:30:00\" with start_timezone \"America/New_York\"; the server resolves it to UTC. An offset-bearing RFC 3339 value (e.g. \"2026-06-06T09:30:00-04:00\") is also accepted and validated against the zone. All-day events: set is_all_day true and send date-only start_date/end_date (end_date exclusive) instead of start_time/end_time.",
        "operationId": "createProfileEvent",
        "tags": [
          "Profiles",
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/profiles/{profile_id}/series": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProfileId"
        }
      ],
      "get": {
        "summary": "List a profile's series",
        "description": "Returns series belonging to the specified profile.",
        "operationId": "listProfileSeries",
        "tags": [
          "Profiles",
          "Series"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SeriesPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create series for a profile",
        "description": "Creates a series under a profile owned by the authenticated user. `slug` must be unique within the profile; conflicts return 409.",
        "operationId": "createProfileSeries",
        "tags": [
          "Profiles",
          "Series"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SeriesCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Series"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/profiles/{profile_id}/followers": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProfileId"
        }
      ],
      "get": {
        "summary": "List followers of a profile",
        "description": "Returns users following the specified profile. Only returned if the profile is public, or if the authenticated user owns the profile.",
        "operationId": "listProfileFollowers",
        "tags": [
          "Profiles",
          "Follows"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FollowPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events": {
      "get": {
        "summary": "List events",
        "description": "Returns a global feed of events visible to the authenticated user — a discovery feed that may include public events you do not manage. To act on events you can edit, resolve them by drilling down from `listProfiles` to `listProfileEvents`, or use `listCalendarEvents` for a user's personal calendar view. Returns base event rows as stored, not expanded recurrence occurrences — expanding a recurrence rule into individual occurrences is a client-side concern.",
        "operationId": "listEvents",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create event",
        "description": "Creates an event owned by the authenticated user. `profile_id` is required in the body to specify the parent profile. \n\nTime formats — timed events: send a naive local time plus a timezone (recommended), e.g. start_time \"2026-06-06T09:30:00\" with start_timezone \"America/New_York\"; the server resolves it to UTC. An offset-bearing RFC 3339 value (e.g. \"2026-06-06T09:30:00-04:00\") is also accepted and validated against the zone. All-day events: set is_all_day true and send date-only start_date/end_date (end_date exclusive) instead of start_time/end_time.",
        "operationId": "createEvent",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        },
        {
          "$ref": "#/components/parameters/Expand"
        }
      ],
      "get": {
        "summary": "Retrieve event",
        "description": "Returns a single event by ID. Use the `expand` query parameter to inline related resources (e.g., RSVPs). Returns the base event row as stored, not an expanded recurrence occurrence.",
        "operationId": "getEvent",
        "tags": [
          "Events"
        ],
        "responses": {
          "200": {
            "description": "Event",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "summary": "Update event",
        "description": "Updates fields on an event owned by the authenticated user. Cancelling or rescheduling an event has dedicated endpoints (`POST /v1/events/{event_id}/cancel`, `POST /v1/events/{event_id}/reschedule`) that handle the side effects on RSVPs.",
        "operationId": "updateEvent",
        "tags": [
          "Events"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete event",
        "description": "Permanently deletes an event and its RSVPs. For a softer flow that preserves attendee history and notifies them, use `cancelEvent` instead.",
        "operationId": "deleteEvent",
        "tags": [
          "Events"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}/cancel": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        }
      ],
      "post": {
        "summary": "Cancel event",
        "description": "Marks an event as cancelled and records an optional `reason`. RSVP records are preserved so attendees can be notified; the event itself is no longer mutable until rescheduled.",
        "operationId": "cancelEvent",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventCancel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}/reschedule": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        }
      ],
      "post": {
        "summary": "Reschedule event",
        "description": "Updates an event's `start_time` (and optionally `end_time`) and flags the event as rescheduled. Distinct from `updateEvent` because rescheduling is the moment to notify attendees and reset acknowledgement state.",
        "operationId": "rescheduleEvent",
        "tags": [
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventReschedule"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rescheduled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}/rsvps": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        }
      ],
      "get": {
        "summary": "List RSVPs",
        "description": "Returns RSVPs for an event. Only the event's owner sees full attendee details; non-owners see a redacted view limited to status counts and the caller's own RSVP if present.",
        "operationId": "listEventRsvps",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RsvpPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create RSVP",
        "description": "Creates or replaces the authenticated user's RSVP for an event. Calling again with a different `status` updates the existing RSVP rather than creating a duplicate.",
        "operationId": "createEventRsvp",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RsvpCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rsvp"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}/rsvps/{rsvp_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        },
        {
          "$ref": "#/components/parameters/RsvpId"
        }
      ],
      "patch": {
        "summary": "Update RSVP",
        "description": "Updates an existing RSVP. Only the RSVP owner or the event owner can modify; others receive 404.",
        "operationId": "updateEventRsvp",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RsvpUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rsvp"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete RSVP",
        "description": "Withdraws an RSVP. Equivalent to setting status to `not_going` but also removes the record from the event's attendee count.",
        "operationId": "deleteEventRsvp",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}/rsvps/stats": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        }
      ],
      "get": {
        "summary": "RSVP statistics",
        "description": "Returns aggregate RSVP counts by status (going, maybe, not_going, waitlist) plus total attendee count. Available to anyone who can see the event.",
        "operationId": "getEventRsvpStats",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "responses": {
          "200": {
            "description": "Stats",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RsvpStats"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/events/{event_id}/rsvp-settings": {
      "parameters": [
        {
          "$ref": "#/components/parameters/EventId"
        }
      ],
      "get": {
        "summary": "Get RSVP settings",
        "description": "Returns the event's RSVP configuration (capacity, waitlist, notification policies).",
        "operationId": "getEventRsvpSettings",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "responses": {
          "200": {
            "description": "Settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RsvpSettings"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "summary": "Update RSVP settings",
        "description": "Updates the event's RSVP configuration. Owner-only. Reducing capacity below current attendee count does not retroactively remove RSVPs but does prevent new ones.",
        "operationId": "updateEventRsvpSettings",
        "tags": [
          "Events",
          "RSVPs"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RsvpSettingsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RsvpSettings"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/series": {
      "get": {
        "summary": "List series",
        "description": "Returns the series the authenticated caller can manage — those they own directly or administer through an organization they belong to. This is a workflow endpoint, not platform-wide discovery: public series owned by others are not returned. Use it to resolve a name to a series you can write to. Use `listProfileSeries` to scope to a single profile.",
        "operationId": "listSeries",
        "tags": [
          "Series"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SeriesPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/series/{series_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SeriesId"
        }
      ],
      "get": {
        "summary": "Retrieve series",
        "description": "Returns a single series by ID.",
        "operationId": "getSeries",
        "tags": [
          "Series"
        ],
        "responses": {
          "200": {
            "description": "Series",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Series"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "summary": "Update series",
        "description": "Updates fields on a series owned by the authenticated user. The `slug` is unique within the parent profile; conflicts return 409.",
        "operationId": "updateSeries",
        "tags": [
          "Series"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SeriesUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Series"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete series",
        "description": "Deletes a series. By default, events that belong only to this series are preserved; pass `cascade_exclusive_events=true` to also delete them. Use `previewSeriesDeletion` first to see what would be removed.",
        "operationId": "deleteSeries",
        "tags": [
          "Series"
        ],
        "parameters": [
          {
            "name": "cascade_exclusive_events",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "If true, also delete events that belong only to this series. Events shared with other series are preserved."
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SeriesDeletion"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/series/{series_id}/deletion-preview": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SeriesId"
        }
      ],
      "get": {
        "summary": "Preview series deletion",
        "description": "Returns a read-only preview of what `deleteSeries` would affect: the series itself, plus the list of events that would be removed if `cascade_exclusive_events=true` is passed. Does not modify anything.",
        "operationId": "previewSeriesDeletion",
        "tags": [
          "Series"
        ],
        "responses": {
          "200": {
            "description": "Deletion impact summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SeriesDeletionPreview"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/series/{series_id}/events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SeriesId"
        }
      ],
      "get": {
        "summary": "List events in a series",
        "description": "Returns events in the specified series, ordered by start time.",
        "operationId": "listSeriesEvents",
        "tags": [
          "Series",
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Add event to series",
        "description": "Adds an existing event to the series. The event and series must both be owned by the authenticated user. Adding an event that is already in the series is a no-op.",
        "operationId": "addEventToSeries",
        "tags": [
          "Series",
          "Events"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SeriesAddEvent"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Linked",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/series/{series_id}/events/{event_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SeriesId"
        },
        {
          "$ref": "#/components/parameters/EventId"
        }
      ],
      "delete": {
        "summary": "Remove event from series",
        "description": "Removes the event-series link but does not delete the event itself. Inverse of `addEventToSeries`.",
        "operationId": "removeEventFromSeries",
        "tags": [
          "Series",
          "Events"
        ],
        "responses": {
          "204": {
            "description": "Removed",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/calendars": {
      "get": {
        "summary": "List calendars",
        "description": "Returns the authenticated user's calendars. Calendars are personal; this endpoint is scoped to the caller only.",
        "operationId": "listCalendars",
        "tags": [
          "Calendars"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/calendars/{calendar_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CalendarId"
        }
      ],
      "get": {
        "summary": "Retrieve calendar",
        "description": "Returns a single calendar owned by the authenticated user.",
        "operationId": "getCalendar",
        "tags": [
          "Calendars"
        ],
        "responses": {
          "200": {
            "description": "Calendar",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Calendar"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/calendars/{calendar_id}/events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CalendarId"
        }
      ],
      "get": {
        "summary": "List calendar events",
        "description": "Stored events on one Everyday calendar, ordered by creation time. Includes personal events and materialized profile subscription events; recurring personal series remain stored rows with a rule. Connected provider events are excluded. Use GET /v1/agenda for a time-window schedule.",
        "operationId": "listCalendarEvents",
        "tags": [
          "Calendars"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEventPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create calendar event",
        "description": "Creates a personal event on the authenticated user's calendar. Distinct from `POST /v1/events`, which creates public-facing profile events.",
        "operationId": "createCalendarEvent",
        "tags": [
          "Calendars"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalendarEventCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEvent"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/calendars/{calendar_id}/events/{event_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CalendarId"
        },
        {
          "$ref": "#/components/parameters/CalendarEventId"
        }
      ],
      "patch": {
        "summary": "Update calendar event",
        "description": "Updates a personal calendar event. Only events created via `createCalendarEvent` are mutable here; subscription-synced events are read-only and changes must be made on the source profile.",
        "operationId": "updateCalendarEvent",
        "tags": [
          "Calendars"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalendarEventUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarEvent"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete calendar event",
        "description": "Deletes a personal calendar event. Subscription-synced events cannot be deleted this way — unsubscribe from the source via `deleteSubscription` instead.",
        "operationId": "deleteCalendarEvent",
        "tags": [
          "Calendars"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/subscriptions": {
      "get": {
        "summary": "List subscriptions",
        "description": "Returns the authenticated user's active and inactive subscriptions to profiles or series.",
        "operationId": "listSubscriptions",
        "tags": [
          "Subscriptions"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create subscription",
        "description": "Subscribes the authenticated user to a profile or series. The corresponding events are then synced into `target_calendar_id` (or the user's default personal calendar if omitted).",
        "operationId": "createSubscription",
        "tags": [
          "Subscriptions"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscriptionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/subscriptions/{subscription_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SubscriptionId"
        }
      ],
      "get": {
        "summary": "Retrieve subscription",
        "description": "Returns a subscription owned by the authenticated user.",
        "operationId": "getSubscription",
        "tags": [
          "Subscriptions"
        ],
        "responses": {
          "200": {
            "description": "Subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "summary": "Update subscription",
        "description": "Updates a subscription's sync window or active state. Setting `is_active: false` stops new events from syncing but does not retroactively remove events that were already synced.",
        "operationId": "updateSubscription",
        "tags": [
          "Subscriptions"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscriptionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete subscription",
        "description": "Unsubscribes from the source. Events that were synced under this subscription are removed from the target calendar.",
        "operationId": "deleteSubscription",
        "tags": [
          "Subscriptions"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/follows": {
      "get": {
        "summary": "List follows",
        "description": "Returns follows owned by the authenticated user (i.e., who the caller is following).",
        "operationId": "listFollows",
        "tags": [
          "Follows"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FollowPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "summary": "Create follow",
        "description": "Creates a follow relationship from the authenticated user to a profile, series, or event. Duplicate follows are not created; calling again returns the existing follow.",
        "operationId": "createFollow",
        "tags": [
          "Follows"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FollowCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Follow"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/follows/{follow_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FollowId"
        }
      ],
      "delete": {
        "summary": "Delete follow",
        "description": "Unfollows. Idempotent — deleting an already-deleted follow is a no-op.",
        "operationId": "deleteFollow",
        "tags": [
          "Follows"
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/search": {
      "get": {
        "summary": "Search across events, profiles, and series",
        "description": "Cross-resource search across events, profiles, and series. Use the `type` query parameter to narrow to a subset (e.g., `type=events,profiles`). Results are paginated via `cursor`.",
        "operationId": "search",
        "tags": [
          "Search"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Search query string. Matched against event titles/descriptions, profile names/everyday_ids, and series names. Whitespace is significant for phrase matching.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Comma-separated list of resource types to include in the results. Allowed values: `events`, `profiles`, `series`. Omit to search across all three.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResult"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "summary": "MCP Server (consumer / OAuth)",
        "description": "Consumer-facing MCP server, OAuth-only. Usage logged to mcp_consumer_usage; billed via the Everyday consumer subscription system. For API-key access, use /mcp-developer. The operations array on this route must be a SUBSET of /mcp-developer's; see scripts/check-mcp-operations-superset.mjs.",
        "operationId": "mcpServer",
        "tags": [
          "MCP"
        ],
        "responses": {
          "200": {
            "description": "JSON-RPC response envelope. Successful tool invocations include `result`; tool-level failures (including downstream HTTP errors from the proxied REST endpoint) are returned as `result.content` with `isError: true` per the MCP spec, not as JSON-RPC `error`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/mcp-developer": {
      "post": {
        "summary": "MCP Server (developer / API key)",
        "description": "Developer-facing MCP server, API-key-only. Billed via Zuplo monetization (same meter as direct API calls). For OAuth-delegated consumer use, point your MCP client at /mcp. The operations array on this route must be a SUPERSET of /mcp's; see scripts/check-mcp-operations-superset.mjs.",
        "operationId": "mcpServerDeveloper",
        "tags": [
          "MCP"
        ],
        "responses": {
          "200": {
            "description": "JSON-RPC response envelope. Successful tool invocations include `result`; tool-level failures (including downstream HTTP errors from the proxied REST endpoint) are returned as `result.content` with `isError: true` per the MCP spec, not as JSON-RPC `error`.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/external-calendars": {
      "get": {
        "summary": "List connected external calendars",
        "description": "Lists connected calendars visible to the caller. Use xcal_ IDs as external subscription targets; cal_ identifies an Everyday personal calendar.",
        "operationId": "listExternalCalendars",
        "tags": [
          "Calendars"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExternalCalendarPage"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/organizations": {
      "get": {
        "summary": "List available organizations",
        "description": "Lists active organizations available to the authenticated caller for profile creation. The single active organization the caller owns is marked is_default. This endpoint does not select or mutate server-side session state.",
        "operationId": "listOrganizations",
        "tags": [
          "Organizations"
        ],
        "responses": {
          "200": {
            "description": "Available organizations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationList"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/agenda": {
      "get": {
        "summary": "Read your agenda",
        "description": "Read-only combined schedule over 1–31 local days. The entire window must fall within 30 days back and 365 days ahead, measured in the resolved timezone. These are query bounds, not a promise of source coverage. At most 500 sorted occurrences; complete=false reports query or expansion truncation. Sources include empty calendars; warnings indicate unknown, failed, disabled, old, or unverified sync state. Connected calendars reflect available synced data, not a live provider request. No-end events are points; all-day end dates are exclusive. RSVPs not saved to a calendar are excluded.",
        "operationId": "getAgenda",
        "tags": [
          "Calendars"
        ],
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "First local calendar day, YYYY-MM-DD. Defaults to today in the resolved timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Window length in local days. For this week, choose the week start as date; seven days from today is a rolling week.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 31,
              "default": 1
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "IANA timezone. Defaults to the saved user timezone, then UTC.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_ids",
            "in": "query",
            "required": false,
            "description": "Optional comma-separated list of 1–100 exact cal_ or xcal_ IDs. Defaults to all Everyday calendars and selected eligible connected calendars.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "detail",
            "in": "query",
            "required": false,
            "description": "Summary includes titles, times, location and source. Full also includes description.",
            "schema": {
              "type": "string",
              "enum": [
                "summary",
                "full"
              ],
              "default": "summary"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Combined agenda of matching stored occurrences",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agenda"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  }
}