The Index Indexes API

Approved indie web and small web index sites.

OpenAPI Specification

the-index-fyi-indexes-api-openapi.yml Raw ↑
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