{
  "openapi": "3.0.1",
  "info": {
    "title": "Ticker Data API",
    "description": "Ticker Data API for programmatic access to market data",
    "version": "2.5.0"
  },
  "servers": [
    {
      "url": "https://api.tickerapp.net/v2"
    }
  ],
  "tags": [
    {
      "name": "Disclosures",
      "description": "Regulatory disclosure announcements from UK markets"
    },
    {
      "name": "References",
      "description": "Reference data for exchanges"
    }
  ],
  "paths": {
    "/disclosures/sources/rns/items": {
      "get": {
        "tags": [
          "Disclosures"
        ],
        "summary": "List RNS disclosure items",
        "description": "Returns a paginated list of disclosure items from the RNS source, filtered by time range, instruments, categories and/or full-text query.\n",
        "operationId": "listRnsDisclosureItems",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "dateFrom",
            "in": "query",
            "description": "Filter items released on or after this date/time. **Default:** If not provided, defaults to 30 days before `dateTo` (or 30 days ago if `dateTo` is also omitted). This default does not apply when filtering by `symbols` or `isins`. Accepts partial ISO8601 dates that expand to the start of the period: `2025` → Jan 1st 00:00, `2025-11` → Nov 1st 00:00, `2025-12-31` → Dec 31st 00:00, `2025-12-31T14:30` → 14:30:00.\n",
            "required": false,
            "schema": {
              "type": "string"
            },
            "examples": {
              "year": {
                "value": "2025",
                "summary": "Full year"
              },
              "month": {
                "value": "2025-11",
                "summary": "Full month"
              },
              "day": {
                "value": "2025-12-31",
                "summary": "Full day"
              },
              "datetime": {
                "value": "2025-12-31T14:30:00Z",
                "summary": "Specific time"
              }
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "description": "Filter items released on or before this date/time. Accepts partial ISO8601 dates that expand to the end of the period: `2025` → Dec 31st 23:59:59, `2025-11` → Nov 30th 23:59:59, `2025-12-31` → Dec 31st 23:59:59, `2025-12-31T14:30` → 14:30:59.\n",
            "required": false,
            "schema": {
              "type": "string"
            },
            "examples": {
              "year": {
                "value": "2025",
                "summary": "Full year"
              },
              "month": {
                "value": "2025-11",
                "summary": "Full month"
              },
              "day": {
                "value": "2025-12-31",
                "summary": "Full day"
              },
              "datetime": {
                "value": "2025-12-31T14:30:00Z",
                "summary": "Specific time"
              }
            }
          },
          {
            "name": "isins",
            "in": "query",
            "description": "Filter by one or more ISINs (comma-separated). Example: `isins=GB00AAA1111,GB00BBB2222`. Use either `isins` (comma-separated) or `isin` (repeated), not both.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "isin",
            "in": "query",
            "description": "Filter by one or more ISINs (repeated parameter). Example: `isin=GB00AAA1111&isin=GB00BBB2222`. If both `isins` and `isin` are provided, `isin` is ignored and a warning is returned.\n",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "symbols",
            "in": "query",
            "description": "Filter by ticker symbols (comma-separated). Example: `symbols=VOD,LLOY`. Use either `symbols` (comma-separated) or `symbol` (repeated), not both.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "description": "Filter by ticker symbols (repeated parameter). Example: `symbol=VOD&symbol=LLOY`. If both `symbols` and `symbol` are provided, `symbol` is ignored and a warning is returned.\n",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "fcaCategories",
            "in": "query",
            "description": "Filter by FCA category codes (comma-separated). Example: `fcaCategories=FR,HOL,BOA`. Use either `fcaCategories` (comma-separated) or `fcaCategory` (repeated), not both.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fcaCategory",
            "in": "query",
            "description": "Filter by FCA category codes (repeated parameter). Example: `fcaCategory=FR&fcaCategory=HOL`. If both `fcaCategories` and `fcaCategory` are provided, `fcaCategory` is ignored and a warning is returned.\n",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "tickerCategories",
            "in": "query",
            "description": "Filter by Ticker category codes (comma-separated). Example: `tickerCategories=RE,HO,BC`. Use either `tickerCategories` (comma-separated) or `tickerCategory` (repeated), not both.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tickerCategory",
            "in": "query",
            "description": "Filter by Ticker category codes (repeated parameter). Example: `tickerCategory=RE&tickerCategory=HO`. If both `tickerCategories` and `tickerCategory` are provided, `tickerCategory` is ignored and a warning is returned.\n",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Full-text search over headline",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Number of items per page (default 50, max 200)",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "pageCursor",
            "in": "query",
            "description": "Opaque cursor for cursor-based pagination. Mutually exclusive with `pageNumber` and `sinceCursor`.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageNumber",
            "in": "query",
            "description": "Page number for classic pagination (1-indexed). Mutually exclusive with `pageCursor` and `sinceCursor`.\n",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "sinceCursor",
            "in": "query",
            "description": "Poll for items newer than this cursor value. Returns only items with a cursor greater than the provided value, ordered newest first. Designed for lightweight real-time polling — when no new items exist, the query returns immediately with zero results. The response includes `latestCursor` (the cursor of the newest returned item, or the original value if no results) for use in the next poll. Mutually exclusive with `pageCursor` and `pageNumber`.\n",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hasSymbol",
            "in": "query",
            "description": "Filter to items where the issuer has a ticker symbol. Use `hasSymbol=true` to only return items with a symbol.\n",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "description": "Filter by distribution channel. Each channel corresponds to items categorized for specific distribution targets. Enterprise-only feature.\n",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "app",
                "bot",
                "internal",
                "social",
                "widget"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of RNS disclosure items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DisclosureItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Optional warnings about the request. For example, if a filter parameter was ignored because it is not available on the current plan, or if both singular and plural array parameter formats were provided.\n"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid filter or pagination parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/disclosures/sources/rns/items/{identifier}": {
      "get": {
        "tags": [
          "Disclosures"
        ],
        "summary": "Get a single RNS disclosure item",
        "description": "Returns a single disclosure item by its identifier. Accepts either a GUID or rnsDateId format (auto-detected by length).\n",
        "operationId": "getRnsDisclosureItem",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "description": "The disclosure item identifier. Accepts two formats: - **GUID**: The globally unique identifier (e.g., `urn:newsml:londonstockexchange.com:20251231:1234A:1`) - **rnsDateId**: A 16-character composite key in format `yyyy-mm-dd.rnsId` (e.g., `2025-12-31.1234A`)\nThe format is auto-detected by length: exactly 16 characters = rnsDateId, otherwise GUID.\n",
            "required": true,
            "schema": {
              "type": "string"
            },
            "examples": {
              "guid": {
                "value": "urn:newsml:londonstockexchange.com:20251231:1234A:1",
                "summary": "GUID format"
              },
              "rnsDateId": {
                "value": "2025-12-31.1234A",
                "summary": "rnsDateId format (16 chars)"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The requested disclosure item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DisclosureItem"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Disclosure item not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/references/exchanges": {
      "get": {
        "tags": [
          "References"
        ],
        "summary": "List exchanges",
        "description": "Returns a list of supported exchanges.",
        "operationId": "listExchanges",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageCursor"
          },
          {
            "$ref": "#/components/parameters/PageNumber"
          }
        ],
        "responses": {
          "200": {
            "description": "List of exchanges",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ExchangeListItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/references/exchanges/{mic}": {
      "get": {
        "tags": [
          "References"
        ],
        "summary": "Get exchange details",
        "description": "Returns detailed information for a single exchange by MIC.",
        "operationId": "getExchange",
        "security": [],
        "parameters": [
          {
            "name": "mic",
            "in": "path",
            "description": "Exchange MIC (e.g., XLON)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Exchange details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExchangeDetail"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "description": "Error response wrapper",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        },
        "required": [
          "error"
        ]
      },
      "ErrorDetail": {
        "type": "object",
        "description": "Error details",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable error message",
            "example": "Pagination conflict"
          },
          "hint": {
            "type": "string",
            "description": "Suggestion for resolving the error",
            "example": "Use either pageCursor or pageNumber, not both."
          }
        },
        "required": [
          "message"
        ]
      },
      "Meta": {
        "type": "object",
        "description": "Response metadata (information about the data, such as pagination)",
        "properties": {
          "paging": {
            "$ref": "#/components/schemas/Paging"
          }
        },
        "required": [
          "paging"
        ]
      },
      "Paging": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/CursorPaging"
          },
          {
            "$ref": "#/components/schemas/ClassicPaging"
          },
          {
            "$ref": "#/components/schemas/SinceCursorPaging"
          }
        ],
        "description": "Pagination response. Format depends on which parameter was used: `pageCursor` → CursorPaging, `pageNumber` → ClassicPaging, `sinceCursor` → SinceCursorPaging.\n"
      },
      "CursorPaging": {
        "type": "object",
        "description": "Cursor-based pagination response",
        "properties": {
          "pageSize": {
            "type": "integer",
            "description": "Number of items per page"
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Cursor to request the next page, or null if no more results"
          },
          "latestCursor": {
            "type": "string",
            "description": "Cursor of the newest item in the response. Use as `sinceCursor` to poll for new items."
          }
        },
        "required": [
          "pageSize",
          "nextCursor"
        ]
      },
      "ClassicPaging": {
        "type": "object",
        "description": "Classic page-based pagination response",
        "properties": {
          "pageSize": {
            "type": "integer",
            "description": "Number of items per page"
          },
          "pageNumber": {
            "type": "integer",
            "description": "Current page number (1-indexed)"
          },
          "pageTotal": {
            "type": "integer",
            "description": "Total number of pages"
          },
          "itemTotal": {
            "type": "integer",
            "description": "Total number of items matching the query"
          },
          "latestCursor": {
            "type": "string",
            "description": "Cursor of the newest item in the response. Use as `sinceCursor` to poll for new items."
          }
        },
        "required": [
          "pageSize",
          "pageNumber",
          "pageTotal",
          "itemTotal"
        ]
      },
      "SinceCursorPaging": {
        "type": "object",
        "description": "Response for `sinceCursor` polling. Returns items newer than the provided cursor.\n",
        "properties": {
          "pageSize": {
            "type": "integer",
            "description": "Maximum items per response"
          },
          "latestCursor": {
            "type": "string",
            "description": "Cursor of the newest item returned. Use this value as `sinceCursor` in the next poll. If no new items, echoes back the original `sinceCursor` value.\n"
          },
          "count": {
            "type": "integer",
            "description": "Number of items returned in this response"
          },
          "hasMore": {
            "type": "boolean",
            "description": "True if more items exist beyond `pageSize`. When true, the response contains the newest `pageSize` items but older new items were truncated.\n"
          }
        },
        "required": [
          "pageSize",
          "latestCursor",
          "count",
          "hasMore"
        ]
      },
      "DisclosureItem": {
        "type": "object",
        "properties": {
          "rnsId": {
            "type": "string",
            "description": "Native RNS identifier",
            "example": "1234W"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Publication timestamp"
          },
          "source": {
            "type": "string",
            "example": "RNS",
            "description": "Source code"
          },
          "guid": {
            "type": "string",
            "description": "Globally unique identifier"
          },
          "version": {
            "type": "integer",
            "description": "Version number (extracted from guid)"
          },
          "issuer": {
            "$ref": "#/components/schemas/Company"
          },
          "related": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Company"
            },
            "description": "Related companies mentioned in the disclosure"
          },
          "headline": {
            "type": "string",
            "description": "Disclosure headline"
          },
          "category": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Category"
            },
            "description": "Categories (Ticker and FCA)"
          },
          "publication": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Publication"
            },
            "description": "Available document formats"
          },
          "derivatives": {
            "$ref": "#/components/schemas/Derivatives"
          },
          "replaces": {
            "description": "If this is a replacement, details of the replaced announcement",
            "allOf": [
              {
                "$ref": "#/components/schemas/Replaces"
              }
            ]
          }
        },
        "required": [
          "rnsId",
          "timestamp",
          "source",
          "guid",
          "version",
          "issuer",
          "headline",
          "category",
          "publication"
        ]
      },
      "Company": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Company name"
          },
          "lei": {
            "type": "string",
            "description": "Legal Entity Identifier"
          },
          "instrument": {
            "$ref": "#/components/schemas/Instrument"
          }
        },
        "required": [
          "name"
        ]
      },
      "Instrument": {
        "type": "object",
        "properties": {
          "isin": {
            "type": "string",
            "description": "ISIN code"
          },
          "symbol": {
            "$ref": "#/components/schemas/Symbol"
          }
        },
        "required": [
          "isin"
        ]
      },
      "Symbol": {
        "type": "object",
        "properties": {
          "mnemonic": {
            "type": "string",
            "description": "Ticker symbol"
          }
        },
        "required": [
          "mnemonic"
        ]
      },
      "Category": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "Ticker",
              "FCA"
            ],
            "description": "Category type"
          },
          "code": {
            "type": "string",
            "description": "Category code"
          },
          "name": {
            "type": "string",
            "description": "Category name"
          },
          "description": {
            "type": "string",
            "description": "Category description (FCA only)"
          },
          "importance": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "ultra"
            ],
            "description": "Importance level (FCA only)"
          }
        },
        "required": [
          "kind",
          "code",
          "name"
        ]
      },
      "Publication": {
        "type": "object",
        "properties": {
          "mime": {
            "type": "string",
            "description": "MIME type",
            "example": "application/pdf"
          },
          "url": {
            "type": "string",
            "description": "URL to the document"
          }
        },
        "required": [
          "mime",
          "url"
        ]
      },
      "Derivatives": {
        "type": "object",
        "description": "Information derived from the announcement content",
        "properties": {
          "semanticHtml": {
            "type": "object",
            "description": "Token-optimised pure semantic HTML representation of the announcement.\nOnly styles, layout, metadata, attributes and wasted nested tags are removed.\nAll text information that materially makes the content of the announcement remains intact.\n",
            "properties": {
              "url": {
                "type": "string",
                "format": "uri",
                "description": "URL to the semantic HTML document"
              }
            },
            "required": [
              "url"
            ]
          }
        }
      },
      "Replaces": {
        "type": "object",
        "properties": {
          "guid": {
            "type": "string",
            "description": "GUID of the replaced announcement"
          },
          "version": {
            "type": "integer",
            "description": "Version of the replaced announcement"
          }
        },
        "required": [
          "guid",
          "version"
        ]
      },
      "ExchangeSegment": {
        "type": "object",
        "description": "A segment MIC within an exchange",
        "properties": {
          "mic": {
            "type": "string",
            "description": "Segment MIC code",
            "example": "XLOM"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Segment name"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Segment status (ACTIVE, UPDATED, EXPIRED)"
          }
        },
        "required": [
          "mic"
        ]
      },
      "ExchangeListItem": {
        "type": "object",
        "description": "Exchange summary for list responses",
        "properties": {
          "mic": {
            "type": "string",
            "description": "Market Identifier Code (operating MIC)",
            "example": "XLON"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Exchange name"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "ISO 3166 country code",
            "example": "GB"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "City name",
            "example": "LONDON"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "MIC status (ACTIVE, UPDATED, EXPIRED)",
            "example": "ACTIVE"
          },
          "comments": {
            "type": "string",
            "nullable": true,
            "description": "Additional comments from ISO registry"
          }
        },
        "required": [
          "mic"
        ]
      },
      "ExchangeDetail": {
        "type": "object",
        "description": "Full exchange details (ISO 10383 MIC data)",
        "properties": {
          "mic": {
            "type": "string",
            "description": "Market Identifier Code (operating MIC)",
            "example": "XLON"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Exchange name"
          },
          "abbreviation": {
            "type": "string",
            "nullable": true,
            "description": "Exchange abbreviation"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "ISO 3166 country code",
            "example": "GB"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "City name",
            "example": "LONDON"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "MIC status (ACTIVE, UPDATED, EXPIRED)",
            "example": "ACTIVE"
          },
          "website": {
            "type": "string",
            "nullable": true,
            "description": "Exchange website URL"
          },
          "creationDate": {
            "type": "string",
            "nullable": true,
            "description": "ISO date when MIC was created",
            "example": "2005-06-27"
          },
          "lastUpdateDate": {
            "type": "string",
            "nullable": true,
            "description": "ISO date when MIC was last updated",
            "example": "2024-10-28"
          },
          "expiryDate": {
            "type": "string",
            "nullable": true,
            "description": "ISO date when MIC expired (null if active)"
          },
          "comments": {
            "type": "string",
            "nullable": true,
            "description": "Additional comments from ISO registry"
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExchangeSegment"
            },
            "description": "Segment MICs operating under this exchange"
          },
          "_links": {
            "type": "object",
            "properties": {
              "self": {
                "type": "string",
                "description": "Link to this resource"
              }
            }
          }
        },
        "required": [
          "mic",
          "segments",
          "_links"
        ]
      }
    },
    "parameters": {
      "ExchangeMic": {
        "name": "exchangeMic",
        "in": "query",
        "description": "Exchange MIC code. Default: `XLON` (London Stock Exchange).\n",
        "required": false,
        "schema": {
          "type": "string",
          "default": "XLON"
        },
        "example": "XLON"
      },
      "SegmentMic": {
        "name": "segmentMic",
        "in": "query",
        "description": "Market segment MIC code to filter results. Common values: - `XLON`: Main Market - `AIMX`: AIM (Alternative Investment Market) - `XLOM`: Professional Securities Market\nIf omitted, returns results from all segments on the exchange.\n",
        "required": false,
        "schema": {
          "type": "string"
        },
        "examples": {
          "mainMarket": {
            "value": "XLON",
            "summary": "Main Market only"
          },
          "aim": {
            "value": "AIMX",
            "summary": "AIM only"
          }
        }
      },
      "Sector": {
        "name": "sector",
        "in": "query",
        "description": "ICB industry sector to filter results. Example: `Finance`, `Technology`, `Healthcare`.\n",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PageSize": {
        "name": "pageSize",
        "in": "query",
        "description": "Number of items per page (default 50, max 200)",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "PageCursor": {
        "name": "pageCursor",
        "in": "query",
        "description": "Cursor for pagination. Mutually exclusive with pageNumber.",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PageNumber": {
        "name": "pageNumber",
        "in": "query",
        "description": "Page number (1-indexed). Mutually exclusive with pageCursor.",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid parameters",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServerError": {
        "description": "Server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    }
  }
}
