openapi: 3.1.0
info:
  title: AI Prompts Hub Public Data API
  version: "1.0.0"
  description: |
    Free public REST API for AI pricing, rate limits, model spec sheets, and
    head-to-head comparison data. CORS-open, edge-cached, no auth. CC-BY-4.0
    license — attribution = a link back to the canonical page.
    Human-readable docs: https://aipromptshub.co/api/docs
  license:
    name: CC-BY-4.0
    url: https://creativecommons.org/licenses/by/4.0/
  contact:
    name: AI Prompts Hub
    url: https://aipromptshub.co/contact
servers:
  - url: https://aipromptshub.co
paths:
  /api/calc:
    get:
      summary: List every cost calculator
      operationId: listCalcs
      responses:
        "200":
          description: Index of calc slugs
          content:
            application/json:
              schema: { $ref: '#/components/schemas/IndexResponse' }
  /api/calc/{slug}:
    get:
      summary: Get a single cost calculator payload
      operationId: getCalc
      parameters:
        - in: path
          name: slug
          required: true
          schema: { type: string }
      responses:
        "200":
          description: Calculator data
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SlugResponse' }
        "404":
          description: Slug not found
          content:
            application/json:
              schema: { $ref: '#/components/schemas/ErrorResponse' }
  /api/limits:
    get:
      summary: List every rate-limit / quota page
      operationId: listLimits
      responses:
        "200":
          description: Index of limits slugs
          content:
            application/json:
              schema: { $ref: '#/components/schemas/IndexResponse' }
  /api/limits/{slug}:
    get:
      summary: Get a single rate-limit / quota payload
      operationId: getLimit
      parameters:
        - in: path
          name: slug
          required: true
          schema: { type: string }
      responses:
        "200":
          description: Limit data
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SlugResponse' }
  /api/vs:
    get:
      summary: List every head-to-head comparison
      operationId: listVs
      responses:
        "200":
          description: Index of vs slugs
          content:
            application/json:
              schema: { $ref: '#/components/schemas/IndexResponse' }
  /api/vs/{slug}:
    get:
      summary: Get a single head-to-head comparison payload
      operationId: getVs
      parameters:
        - in: path
          name: slug
          required: true
          schema: { type: string }
      responses:
        "200":
          description: Comparison data
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SlugResponse' }
  /api/model:
    get:
      summary: List every model spec sheet
      operationId: listModels
      responses:
        "200":
          description: Index of model slugs
          content:
            application/json:
              schema: { $ref: '#/components/schemas/IndexResponse' }
  /api/model/{slug}:
    get:
      summary: Get a single model spec sheet payload
      operationId: getModel
      parameters:
        - in: path
          name: slug
          required: true
          schema: { type: string }
      responses:
        "200":
          description: Model spec data
          content:
            application/json:
              schema: { $ref: '#/components/schemas/SlugResponse' }
components:
  schemas:
    Attribution:
      type: object
      properties:
        canonicalUrl: { type: string, format: uri }
        requirement: { type: string }
        license: { type: string }
      required: [canonicalUrl, requirement, license]
    IndexItem:
      type: object
      properties:
        slug: { type: string }
        title: { type: string }
        description: { type: string }
        url: { type: string, format: uri }
        apiUrl: { type: string, format: uri }
        lastUpdated: { type: string, format: date }
      required: [slug, title, url, apiUrl, lastUpdated]
    IndexResponse:
      type: object
      properties:
        prefix:
          type: string
          enum: [calc, limits, vs, tutorial, model]
        count: { type: integer }
        items:
          type: array
          items: { $ref: '#/components/schemas/IndexItem' }
        docs: { type: string, format: uri }
        attribution:
          type: object
          properties:
            requirement: { type: string }
            license: { type: string }
      required: [prefix, count, items, docs]
    Table:
      type: object
      properties:
        heading: { type: string, nullable: true }
        columns:
          type: array
          items: { type: string }
        rows:
          type: array
          items:
            type: object
            additionalProperties: true
        footnote: { type: string, nullable: true }
    SlugResponse:
      type: object
      properties:
        prefix: { type: string }
        slug: { type: string }
        title: { type: string }
        description: { type: string }
        url: { type: string, format: uri }
        datePublished: { type: string, format: date }
        lastUpdated: { type: string, format: date }
        sources:
          type: array
          items: { type: string, format: uri }
        table: { $ref: '#/components/schemas/Table' }
        sectionTables:
          type: array
          items: { $ref: '#/components/schemas/Table' }
        relatedTools:
          type: array
          items:
            type: object
            properties:
              slug: { type: string }
              label: { type: string }
              url: { type: string, format: uri }
        faqs:
          type: array
          items:
            type: object
            properties:
              question: { type: string }
              answer: { type: string }
        product:
          type: object
          description: schema.org/Product-compatible spec (model endpoint only)
        attribution: { $ref: '#/components/schemas/Attribution' }
      required: [prefix, slug, title, url, lastUpdated, attribution]
    ErrorResponse:
      type: object
      properties:
        error: { type: string }
        message: { type: string }
        hint: { type: string }
      required: [error, message]
