openapi: 3.1.0 info: title: theindex.fyi version: '1.0' description: | A public, read-only API for theindex.fyi — a maintained meta-index of indie web and small web index sites. All responses follow the [JSON:API 1.1](https://jsonapi.org/) specification and use the `application/vnd.api+json` content type. **Rate limiting:** 60 requests per minute per IP. Responses include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `Retry-After` headers. **Versioning:** The API is currently unversioned. If a breaking change is ever necessary, versioning will be introduced via an `API-Version` request header rather than URL prefixes. contact: url: https://theindex.fyi/about servers: - url: https://theindex.fyi/api description: Production tags: - name: Indexes description: Approved indie web and small web index sites. paths: /indexes: get: operationId: listIndexes summary: List indexes description: Returns a paginated, filterable list of all active indexes. tags: [Indexes] parameters: - $ref: '#/components/parameters/FilterCategory' - $ref: '#/components/parameters/FilterLanguage' - $ref: '#/components/parameters/PageNumber' - $ref: '#/components/parameters/PageSize' responses: '200': description: A paginated collection of index resources. content: application/vnd.api+json: schema: $ref: '#/components/schemas/IndexCollection' example: data: - type: indexes id: '1' attributes: name: ooh.directory slug: ooh-directory url: https://ooh.directory description: A curated directory of personal websites and blogs. category: curated_directories language: null accepts_submissions: true last_checked_at: '2026-05-01T12:00:00Z' links: self: https://theindex.fyi/api/indexes/ooh-directory meta: total: 84 per_page: 25 current_page: 1 last_page: 4 links: self: https://theindex.fyi/api/indexes?page[number]=1 first: https://theindex.fyi/api/indexes?page[number]=1 last: https://theindex.fyi/api/indexes?page[number]=4 prev: null next: https://theindex.fyi/api/indexes?page[number]=2 '429': $ref: '#/components/responses/TooManyRequests' /indexes/{slug}: get: operationId: getIndex summary: Get an index description: Returns a single index by its slug. tags: [Indexes] parameters: - name: slug in: path required: true description: The unique slug of the index. schema: type: string example: ooh-directory responses: '200': description: A single index resource. content: application/vnd.api+json: schema: $ref: '#/components/schemas/IndexResource' example: data: type: indexes id: '1' attributes: name: ooh.directory slug: ooh-directory url: https://ooh.directory description: A curated directory of personal websites and blogs. category: curated_directories language: null accepts_submissions: true last_checked_at: '2026-05-01T12:00:00Z' links: self: https://theindex.fyi/api/indexes/ooh-directory '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' components: parameters: FilterCategory: name: filter[category] in: query required: false description: Filter indexes by category. schema: type: string enum: - curated_directories - rss_feed_aggregators - search_engines - random_discovery - constraint_based_clubs - indieweb_infrastructure example: curated_directories FilterLanguage: name: filter[language] in: query required: false description: Filter by ISO 639-1 language code. Omit to return all languages. schema: type: string minLength: 2 maxLength: 2 example: es PageNumber: name: page[number] in: query required: false description: Page number (1-based). schema: type: integer minimum: 1 default: 1 PageSize: name: page[size] in: query required: false description: Number of results per page. Maximum 100. schema: type: integer minimum: 1 maximum: 100 default: 25 schemas: IndexAttributes: type: object required: - name - slug - url - description - category - accepts_submissions properties: name: type: string description: Display name of the index. example: ooh.directory slug: type: string description: URL-safe unique identifier. example: ooh-directory url: type: string format: uri description: The index's URL. example: https://ooh.directory description: type: string description: One-sentence description of what the index is and who it's for. example: A curated directory of personal websites and blogs. category: type: string description: The category this index belongs to. enum: - curated_directories - rss_feed_aggregators - search_engines - random_discovery - constraint_based_clubs - indieweb_infrastructure example: curated_directories language: type: ['string', 'null'] description: ISO 639-1 language code of the index's primary language. Null if English or unknown. example: es accepts_submissions: type: boolean description: Whether this index accepts submissions from the public. example: true last_checked_at: type: ['string', 'null'] format: date-time description: When the link was last verified as live. example: '2026-05-01T12:00:00Z' IndexResourceObject: type: object required: [type, id, attributes, links] properties: type: type: string enum: [indexes] id: type: string description: Unique numeric ID as a string, per JSON:API spec. example: '1' attributes: $ref: '#/components/schemas/IndexAttributes' links: type: object required: [self] properties: self: type: string format: uri example: https://theindex.fyi/api/indexes/ooh-directory IndexResource: type: object required: [data] properties: data: $ref: '#/components/schemas/IndexResourceObject' IndexCollection: type: object required: [data, meta, links] properties: data: type: array items: $ref: '#/components/schemas/IndexResourceObject' meta: type: object required: [total, per_page, current_page, last_page] properties: total: type: integer description: Total number of matching indexes across all pages. example: 84 per_page: type: integer example: 25 current_page: type: integer example: 1 last_page: type: integer example: 4 links: type: object required: [self, first, last] properties: self: type: string format: uri first: type: string format: uri last: type: string format: uri prev: type: ['string', 'null'] format: uri next: type: ['string', 'null'] format: uri ErrorObject: type: object required: [status, title] properties: status: type: string description: HTTP status code as a string. example: '404' title: type: string description: Short, human-readable summary of the problem. example: Not Found detail: type: string description: Human-readable explanation specific to this occurrence. example: No index exists with the slug "not-a-real-index". ErrorDocument: type: object required: [errors] properties: errors: type: array minItems: 1 items: $ref: '#/components/schemas/ErrorObject' responses: NotFound: description: The requested resource does not exist. content: application/vnd.api+json: schema: $ref: '#/components/schemas/ErrorDocument' example: errors: - status: '404' title: Not Found detail: No index exists with the slug "not-a-real-index". TooManyRequests: description: Rate limit exceeded. Wait for the `Retry-After` period before retrying. headers: Retry-After: description: Seconds until the rate limit resets. schema: type: integer example: 42 X-RateLimit-Limit: description: Maximum requests allowed per minute. schema: type: integer example: 60 X-RateLimit-Remaining: description: Requests remaining in the current window. schema: type: integer example: 0 content: application/vnd.api+json: schema: $ref: '#/components/schemas/ErrorDocument' example: errors: - status: '429' title: Too Many Requests detail: Rate limit of 60 requests per minute exceeded. Please slow down.