{
  "openapi": "3.1.0",
  "info": {
    "title": "Muzeek HTTP API",
    "summary": "Discovery documents plus the authenticated Muzeek Events API. No public unauthenticated write surface.",
    "description": "Machine-readable discovery (`/llms.txt`, `/sitemap.xml`, this spec) is unauthenticated.\n\nProduct data APIs require an `X-API-Key` (`mzk_live_…`) created in Settings → API. Named scopes are `read:events` and `write:events`.\n\n`POST /mcp` is authenticated Streamable HTTP (Clerk OAuth Connect or API key). Tools are account-scoped. Unauthenticated requests return 401.\n\nThe Events collection is the documented resource API today; bookings, settlements, and roster writes are not published as a public HTTP API in this spec (those jobs use MCP after Connect).\n\nVersion 1.0.0. URLs are unversioned (`/api/events`). Additive fields are not breaking. A breaking change will use a new version (path or `X-Api-Version`) with Sunset/Deprecation headers and a documented window.\n\nHuman docs: https://muzeek-ku6g38mkz-muzeek.vercel.app/developers",
    "version": "1.0.0",
    "contact": {
      "name": "Muzeek",
      "url": "https://muzeek-ku6g38mkz-muzeek.vercel.app/contact"
    }
  },
  "servers": [
    {
      "url": "https://muzeek-ku6g38mkz-muzeek.vercel.app",
      "description": "Muzeek production"
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "Unauthenticated files agents should fetch first."
    },
    {
      "name": "Events",
      "description": "Authenticated Events API (`read:events` / `write:events`). Same behavior as /developers."
    },
    {
      "name": "MCP",
      "description": "Authenticated Muzeek MCP. Clerk OAuth or API key. Account-scoped tools."
    }
  ],
  "paths": {
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "tags": [
          "Discovery"
        ],
        "summary": "Muzeek llms.txt (when to use, docs links)",
        "description": "Markdown index for agents: when to use Muzeek, how to call the Events API, MCP, and OpenAPI.",
        "security": [],
        "responses": {
          "200": {
            "description": "llms.txt markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemapXml",
        "tags": [
          "Discovery"
        ],
        "summary": "XML sitemap of indexable marketing/docs URLs",
        "description": "Does not enumerate tenant calendars or authenticated app routes.",
        "security": [],
        "responses": {
          "200": {
            "description": "URL set",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpec",
        "tags": [
          "Discovery"
        ],
        "summary": "This OpenAPI 3.1 document",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 JSON",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "get": {
        "operationId": "getMcpStreamableHttp",
        "tags": [
          "MCP"
        ],
        "summary": "Muzeek MCP Streamable HTTP (authenticated)",
        "description": "Account-scoped MCP. Requires a Clerk OAuth access token (Connect) or an API key. Unauthenticated requests return 401 with WWW-Authenticate pointing at protected-resource metadata. Not a public discovery server.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Streamable HTTP session or JSON-RPC result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "postMcpStreamableHttp",
        "tags": [
          "MCP"
        ],
        "summary": "Muzeek MCP Streamable HTTP JSON-RPC (authenticated)",
        "description": "Curated account tools (events, bookings, contacts, invoices, settlements, tickets). Clerk OAuth or API key. Unauthenticated requests return 401.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC or Streamable HTTP response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/events": {
      "get": {
        "operationId": "listEvents",
        "tags": [
          "Events"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "List events in the authenticated account",
        "description": "Paginated event list. Requires `read:events`. Public IDs are UUIDs. See /developers.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Page number."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            },
            "description": "Page size (max 100 for list views)."
          },
          {
            "name": "sortBy",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "startDate",
                "title",
                "createdAt"
              ]
            }
          },
          {
            "name": "sortOrder",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Free-text search across event title."
          },
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "style": "form",
            "explode": true,
            "description": "Repeatable event type keys, e.g. types=show."
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated includes: venue, venue.full, tour, tour.full, account, account.full."
          }
        ],
        "responses": {
          "200": {
            "description": "Event list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createEvent",
        "tags": [
          "Events"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Create an event",
        "description": "Requires `write:events`. `eventType` defaults to `show`; `status` defaults to `private`. Optional `forAccountId` creates the event for a roster member.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created event",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/events/{id}": {
      "get": {
        "operationId": "getEvent",
        "tags": [
          "Events"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Get one event by UUID",
        "description": "Requires `read:events`. Same `include` query as list.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Public UUID (never an internal numeric database id)."
            }
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Event",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateEvent",
        "tags": [
          "Events"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Partial-update an event",
        "description": "Requires `write:events`. Send only fields to change.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Public UUID (never an internal numeric database id)."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated event",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteEvent",
        "tags": [
          "Events"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "summary": "Permanently delete an event",
        "description": "Requires `write:events`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Public UUID (never an internal numeric database id)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventDeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Muzeek API key (`mzk_live_…`) from Settings → API. `Authorization: Bearer` is also accepted. There is no OAuth token endpoint for this HTTP API. Named scopes on the key: `read:events` (list/get) and `write:events` (create/update/delete)."
      }
    },
    "schemas": {
      "Uuid": {
        "type": "string",
        "format": "uuid",
        "description": "Public UUID (never an internal numeric database id)."
      },
      "ApiError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "examples": [
                  "UNAUTHORIZED",
                  "FORBIDDEN",
                  "NOT_FOUND",
                  "RATE_LIMITED"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          }
        }
      },
      "McpManifest": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "protocolVersion",
          "serverInfo"
        ],
        "properties": {
          "protocolVersion": {
            "type": "string"
          },
          "capabilities": {
            "type": "object",
            "additionalProperties": true
          },
          "serverInfo": {
            "type": "object",
            "required": [
              "name",
              "version"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "instructions": {
            "type": "string"
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {},
          "method": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {},
          "result": {
            "additionalProperties": true
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Event": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "id",
          "title",
          "startDate",
          "endDate",
          "timezone",
          "isAllDay"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Public UUID (never an internal numeric database id)."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "eventType": {
            "type": "string",
            "description": "Macro type key (e.g. show)."
          },
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone."
          },
          "isAllDay": {
            "type": "boolean"
          },
          "isPublished": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          },
          "capacity": {
            "type": [
              "integer",
              "null"
            ]
          },
          "imageUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "venueId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "tourId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "venue": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          },
          "tour": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          }
        }
      },
      "EventCreateRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title",
          "startDate",
          "endDate",
          "timezone",
          "isAllDay"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "forAccountId": {
            "type": "string",
            "format": "uuid",
            "description": "Public UUID (never an internal numeric database id)."
          },
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time"
          },
          "timezone": {
            "type": "string"
          },
          "isAllDay": {
            "type": "boolean"
          },
          "venueId": {
            "type": "string",
            "format": "uuid",
            "description": "Public UUID (never an internal numeric database id)."
          },
          "tourId": {
            "type": "string",
            "format": "uuid",
            "description": "Public UUID (never an internal numeric database id)."
          },
          "status": {
            "type": "string"
          },
          "isPublished": {
            "type": "boolean"
          },
          "capacity": {
            "type": "integer",
            "minimum": 1
          },
          "imageUrl": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "EventUpdateRequest": {
        "type": "object",
        "additionalProperties": true,
        "description": "Partial update; omit fields to leave them unchanged. Send null to clear description, venueId, tourId, capacity, or taxRateId.",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "eventType": {
            "type": "string"
          },
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time"
          },
          "timezone": {
            "type": "string"
          },
          "isAllDay": {
            "type": "boolean"
          },
          "venueId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Public UUID; null clears the venue."
          },
          "tourId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Public UUID; null clears the tour."
          },
          "status": {
            "type": "string"
          },
          "isPublished": {
            "type": "boolean"
          },
          "capacity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "imageUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "taxRateId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Public UUID; null clears the tax rate."
          }
        }
      },
      "EventResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Event"
          }
        }
      },
      "EventListResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "ListMeta": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "pagination": {
            "type": "object",
            "properties": {
              "page": {
                "type": "integer",
                "minimum": 1
              },
              "limit": {
                "type": "integer",
                "minimum": 1
              },
              "total": {
                "type": "integer",
                "minimum": 0
              },
              "pages": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "includes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "EventDeleteResponse": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid authentication",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Authenticated but not allowed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "NotFound": {
        "description": "Event not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Validation error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limited. Honor Retry-After and X-RateLimit-Reset.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      }
    }
  }
}
