openapi: 3.1.0 info: title: theindex.fyi Indexes API 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: 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 ErrorDocument: type: object required: - errors properties: errors: type: array minItems: 1 items: $ref: '#/components/schemas/ErrorObject' 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". 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 responses: 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. 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". parameters: PageNumber: name: page[number] in: query required: false description: Page number (1-based). schema: type: integer minimum: 1 default: 1 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 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 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