openapi: 3.0.3
info:
  title: agentes.ai API
  description: 'API pública de agentes.ai — Directorio de agencias de IA y agentes
    AI. Acceso programático a agencias, blog, reseñas y noticias. Base URL: https://www.agentes.ai/api'
  version: 1.0.0
  contact:
    name: agentes.ai
    url: https://www.agentes.ai
    email: contacto@agentes.ai
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
servers:
- url: https://www.agentes.ai/api
  description: Producción (vía CloudFront)
- url: https://nz0piekbg3.execute-api.eu-central-1.amazonaws.com/dev
  description: API Gateway directo
tags:
- name: agencies
  description: Directorio de agencias de IA
- name: blog
  description: Blog IA — análisis diario
- name: reviews
  description: Reseñas de herramientas IA
- name: news
  description: Noticias de IA
- name: system
  description: Sistema y metadatos
paths:
  /agencies:
    get:
      tags:
      - agencies
      summary: Listar agencias
      description: 'Lista agencias publicadas con filtros opcionales. Las agencias
        con plan gratuito vencido se ocultan automáticamente a menos que el admin
        las reactive manualmente. Resultados ordenados: premium primero, luego estándar,
        luego free.'
      parameters:
      - name: q
        in: query
        description: Búsqueda por nombre, expertise o categoría
        required: false
        schema:
          type: string
      - name: category
        in: query
        description: Filtrar por categoría
        required: false
        schema:
          type: string
          enum:
          - Automatización
          - Agentes Autónomos
          - Integraciones
          - Agentes de Voz
          - Consultoría IA
          - Desarrollo a medida
      - name: department
        in: query
        description: Filtrar por departamento
        required: false
        schema:
          type: string
      - name: premium
        in: query
        description: Solo premium
        required: false
        schema:
          type: boolean
      - name: limit
        in: query
        description: Límite (1-200, default 200)
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 200
      responses:
        '200':
          description: Lista de agencias
          content:
            application/json:
              schema:
                type: object
                properties:
                  agencies:
                    type: array
                    items:
                      $ref: '#/components/schemas/Agency'
              example:
                agencies:
                - agencyId: agency-rakaty
                  name: Rakaty Automatizaciones
                  location: Madrid (Alcobendas), España
                  expertise: Automatización de procesos con IA para PYMEs
                  website: https://rakaty.com/
                  contactEmail: contacto@rakaty.com
                  category: Automatización
                  priceFrom: Desde 900€
                  isPremium: true
                  plan: premium
          headers:
            Cache-Control:
              description: Cache pública 120s
              schema:
                type: string
            Vary:
              description: Vary header para negociación de contenido
              schema:
                type: string
  /agencies/{agencyId}/click:
    post:
      tags:
      - agencies
      summary: Registrar click outbound
      description: Fire-and-forget beacon para tracking de clicks a webs de agencias.
        Usa sendBeacon o fetch con keepalive. No requiere auth.
      parameters:
      - name: agencyId
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                source:
                  type: string
                  description: 'Origen del click,ej: home, directorio, ciudad:madrid'
                  example: home
      responses:
        '200':
          description: Click registrado
        '400':
          description: agencyId inválido
  /news:
    get:
      tags:
      - news
      summary: Listar noticias
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
          default: 10
      - name: cursor
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Lista de noticias
          content:
            application/json:
              schema:
                type: object
                properties:
                  news:
                    type: array
                    items:
                      $ref: '#/components/schemas/NewsItem'
                  next_cursor:
                    type: string
                    nullable: true
  /blog:
    get:
      tags:
      - blog
      summary: Listar posts del blog
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 50
          default: 10
      - name: category
        in: query
        schema:
          type: string
          enum:
          - Modelos
          - Herramientas
          - Empresas
          - Regulación
          - Investigación
          - Aplicaciones
      - name: tag
        in: query
        schema:
          type: string
      - name: cursor
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Lista de posts
          content:
            application/json:
              schema:
                type: object
                properties:
                  posts:
                    type: array
                    items:
                      $ref: '#/components/schemas/BlogPostLight'
                  next_cursor:
                    type: string
                    nullable: true
  /blog/{slug}:
    get:
      tags:
      - blog
      summary: Obtener post por slug
      parameters:
      - name: slug
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Post encontrado
          content:
            application/json:
              schema:
                type: object
                properties:
                  post:
                    $ref: '#/components/schemas/BlogPost'
        '404':
          description: Post no encontrado
  /reviews:
    get:
      tags:
      - reviews
      summary: Listar reseñas
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
          default: 10
      - name: category
        in: query
        schema:
          type: string
          enum:
          - Agentes
          - Automatización
          - Chatbots
          - Productividad
          - Desarrollo
          - Marketing
          - Análisis
      - name: cursor
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Lista de reseñas
          content:
            application/json:
              schema:
                type: object
                properties:
                  reviews:
                    type: array
                    items:
                      $ref: '#/components/schemas/ReviewLight'
                  next_cursor:
                    type: string
                    nullable: true
  /reviews/{slug}:
    get:
      tags:
      - reviews
      summary: Obtener reseña por slug
      parameters:
      - name: slug
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Reseña encontrada
          content:
            application/json:
              schema:
                type: object
                properties:
                  review:
                    $ref: '#/components/schemas/Review'
                  related:
                    type: array
                    items:
                      $ref: '#/components/schemas/ReviewLight'
        '404':
          description: Reseña no encontrada
  /openapi.json:
    get:
      tags:
      - system
      summary: OpenAPI spec (este documento)
      responses:
        '200':
          description: OpenAPI JSON
          content:
            application/json:
              schema:
                type: object
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    Agency:
      type: object
      properties:
        agencyId:
          type: string
        name:
          type: string
          example: Rakaty Automatizaciones
        location:
          type: string
          example: Madrid (Alcobendas), España
        expertise:
          type: string
        website:
          type: string
          format: uri
        contactEmail:
          type: string
          format: email
        category:
          type: string
        department:
          type: string
        priceFrom:
          type: string
        isPremium:
          type: boolean
        plan:
          type: string
          enum:
          - free
          - standard
          - premium
        status:
          type: string
          enum:
          - active
          - PENDING_REVIEW
          - PENDING_PAYMENT
        freeUntil:
          type: string
          format: date-time
          nullable: true
    BlogPostLight:
      type: object
      properties:
        slug:
          type: string
        title:
          type: string
        description:
          type: string
        category:
          type: string
        tags:
          type: array
          items:
            type: string
        published_at:
          type: string
          format: date-time
        og_image_url:
          type: string
          format: uri
        reading_time_min:
          type: integer
    BlogPost:
      allOf:
      - $ref: '#/components/schemas/BlogPostLight'
      - type: object
        properties:
          content_html:
            type: string
          content_md:
            type: string
          updated_at:
            type: string
            format: date-time
    ReviewLight:
      type: object
      properties:
        slug:
          type: string
        title:
          type: string
        description:
          type: string
        tool_name:
          type: string
        category:
          type: string
        rating:
          type: number
          minimum: 1
          maximum: 5
        published_at:
          type: string
          format: date-time
        og_image_url:
          type: string
    Review:
      allOf:
      - $ref: '#/components/schemas/ReviewLight'
      - type: object
        properties:
          content_html:
            type: string
          content_md:
            type: string
          tool_url:
            type: string
            format: uri
          affiliate_url:
            type: string
            format: uri
          pricing_summary:
            type: string
          pros:
            type: array
            items:
              type: string
          cons:
            type: array
            items:
              type: string
    NewsItem:
      type: object
      properties:
        date:
          type: string
        newsid:
          type: string
        titulo:
          type: string
        url:
          type: string
          format: uri
        fuente:
          type: string
