openapi: 3.1.0
info:
  title: HookAds API
  version: 1.0.0
  description: |
    Read-only access to the HookAds ad-creative library: AI ad prompts (with attribution), the Hook Bank's
    118 frameworks, ad teardowns, case studies and Meta placement specs. The same data powers the HookAds
    MCP server at https://www.hookads.ai/api/mcp.
    Free plan: 100 calls/day. Any HookAds purchase raises it to 1,000/day on the same key. Max 25 rows per response.
    Create a key at https://www.hookads.ai/dashboard?tab=keys
servers:
  - url: https://www.hookads.ai/api/v1
security:
  - bearer: []
components:
  securitySchemes:
    bearer: { type: http, scheme: bearer, bearerFormat: hka_live_<40 hex> }
  parameters:
    page: { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
    limit: { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 25, default: 10 } }
    q: { name: q, in: query, schema: { type: string } }
  schemas:
    Quota:
      type: object
      properties: { used: { type: integer }, limit: { type: integer }, remaining: { type: integer } }
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code: { type: string, enum: [missing_key, invalid_key, daily_limit_reached, invalid_input, not_found, upstream_unavailable, internal] }
            message: { type: string }
            request_id: { type: string }
            instructions_for_agent: { type: string, description: Present on 402. Relay it to the user. }
            upgrade_url: { type: string }
  responses:
    Unauthorized: { description: Missing, malformed or revoked key, content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } }
    OverQuota: { description: Daily limit reached (includes instructions_for_agent), content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } }
paths:
  /me:
    get:
      summary: Plan and today's quota (not metered)
      responses: { '200': { description: OK }, '401': { $ref: '#/components/responses/Unauthorized' } }
  /prompts:
    get:
      summary: Search AI image and video ad prompts
      parameters:
        - $ref: '#/components/parameters/q'
        - { name: category, in: query, schema: { type: string } }
        - { name: model, in: query, schema: { type: string }, description: e.g. nanobanana, gptimage, veo }
        - { name: media_type, in: query, schema: { type: string, enum: [image, video] } }
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/limit'
      responses: { '200': { description: 'Prompts with model, image_url and attribution' }, '401': { $ref: '#/components/responses/Unauthorized' }, '402': { $ref: '#/components/responses/OverQuota' } }
  /hooks:
    get:
      summary: Hook frameworks (template, why it works, best for, examples)
      parameters:
        - $ref: '#/components/parameters/q'
        - { name: trigger, in: query, schema: { type: string } }
        - { name: format, in: query, schema: { type: string } }
        - { name: awareness, in: query, schema: { type: string } }
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/limit'
      responses: { '200': { description: OK }, '401': { $ref: '#/components/responses/Unauthorized' }, '402': { $ref: '#/components/responses/OverQuota' } }
  /teardowns:
    get:
      summary: List ad teardowns
      parameters: [ { $ref: '#/components/parameters/q' }, { $ref: '#/components/parameters/page' }, { $ref: '#/components/parameters/limit' } ]
      responses: { '200': { description: OK }, '401': { $ref: '#/components/responses/Unauthorized' }, '402': { $ref: '#/components/responses/OverQuota' } }
  /teardowns/{slug}:
    get:
      summary: One teardown as sections
      parameters: [ { name: slug, in: path, required: true, schema: { type: string } } ]
      responses: { '200': { description: OK }, '404': { description: Not found } }
  /case-studies:
    get:
      summary: List advertising case studies
      parameters: [ { $ref: '#/components/parameters/q' }, { $ref: '#/components/parameters/page' }, { $ref: '#/components/parameters/limit' } ]
      responses: { '200': { description: OK }, '401': { $ref: '#/components/responses/Unauthorized' }, '402': { $ref: '#/components/responses/OverQuota' } }
  /case-studies/{slug}:
    get:
      summary: One case study as sections
      parameters: [ { name: slug, in: path, required: true, schema: { type: string } } ]
      responses: { '200': { description: OK }, '404': { description: Not found } }
  /specs:
    get:
      summary: Meta (Facebook + Instagram) placement specs, safe zones and text limits
      parameters: [ { name: placement, in: query, schema: { type: string }, description: e.g. reels, stories, feed } ]
      responses: { '200': { description: OK } }
