openapi: 3.0.3
info:
  title: Yoruba.tech API
  version: "1.3.0"
  description: |
    Public developer API for the Àtùmọ̀ Tech dictionary.

    Billing is prepaid credits (Paystack top-up). Each successful request spends credits.
    Responses include `X-RateLimit-*` (safety throttle), `X-Credit-Balance`, `X-Credit-Cost`, and `X-Commercial-Use`.
    Successful dictionary responses may include optional first-party `meta.sponsored` creatives.
servers:
  - url: /api/v1
paths:
  /dictionary.php:
    get:
      summary: Search approved dictionary terms
      security:
        - bearerAuth: []
        - apiKeyAuth: []
      parameters:
        - in: query
          name: q
          schema: { type: string }
        - in: query
          name: category
          schema: { type: string }
        - in: query
          name: slug
          schema: { type: string }
        - in: query
          name: letter
          schema: { type: string }
        - in: query
          name: limit
          schema: { type: integer, maximum: 500, default: 100 }
      responses:
        "200":
          description: Term list
          headers:
            X-RateLimit-Limit:
              schema: { type: integer }
            X-RateLimit-Remaining:
              schema: { type: integer }
            X-RateLimit-Reset:
              schema: { type: integer }
            X-Credit-Balance:
              schema: { type: integer }
            X-Credit-Cost:
              schema: { type: integer }
            X-Commercial-Use:
              schema: { type: string, enum: ["0", "1"] }
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  meta:
                    type: object
                    properties:
                      source: { type: string }
                      app: { type: string, nullable: true }
                      client_id: { type: string, nullable: true }
                      count: { type: integer }
                      q: { type: string, nullable: true }
                      category: { type: string, nullable: true }
                      slug: { type: string, nullable: true }
                      letter: { type: string, nullable: true }
                      categories:
                        type: array
                        items: { type: string }
                      sponsored:
                        $ref: '#/components/schemas/Sponsored'
                  data:
                    type: array
                    items:
                      type: object
        "402":
          description: Insufficient credits
        "429":
          description: Hourly safety throttle exceeded
  /suggest.php:
    post:
      summary: Submit a dictionary edit suggestion
      security:
        - bearerAuth: []
        - apiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                term_id: { type: integer }
                slug: { type: string }
                suggested_yoruba: { type: string }
                suggested_definition_en: { type: string }
                suggested_definition_yo: { type: string }
                notes: { type: string }
      responses:
        "200":
          description: Suggestion queued
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
  schemas:
    Sponsored:
      type: object
      nullable: true
      description: First-party sponsored creative (null when none is booked)
      properties:
        id: { type: integer }
        headline: { type: string }
        body: { type: string, nullable: true }
        cta_label: { type: string }
        cta_url: { type: string, format: uri }
        image_url: { type: string, format: uri, nullable: true }
        click_url:
          type: string
          format: uri
          description: Tracking redirect URL; prefer this for click-throughs
