openapi: 3.1.0
info:
  title: Veritas UGC API
  version: "1.0.0"
  description: >
    Certificación probatoria de contenido digital. Acredita que un archivo existía en una fecha
    concreta y que no ha cambiado desde entonces, mediante huella SHA-256, anclaje en la cadena de
    Bitcoin (OpenTimestamps) y sello de tiempo RFC 3161.


    NO es un registro estatal de propiedad intelectual, ni de marca, ni una solicitud de patente.
    Acredita que el declarante afirmó ser el autor en una fecha determinada, no que lo sea.


    IMPORTANTE PARA AGENTES: las operaciones de sellado crean BORRADORES. Una persona debe
    aprobarlos desde su panel antes de que se emita ningún certificado.
  contact:
    name: Veritas Nexus Legal LLC
    email: sos@veritasnexuslegal.com
    url: https://ugc.veritasdigital.tech/conectores
  license:
    name: Términos de servicio
    url: https://ugc.veritasdigital.tech/legal/terms

servers:
  - url: https://ugc.veritasdigital.tech/api/v1
    description: Producción

security:
  - ApiKeyAuth: []

paths:
  /health:
    get:
      operationId: healthCheck
      summary: Comprueba que la API está operativa
      security: []
      responses:
        "200":
          description: La API responde correctamente.

  /verify/{slug}:
    get:
      operationId: verifyCertificate
      summary: Verifica un certificado por su identificador público
      description: >
        Público y sin autenticación: la verificación es abierta por diseño. Devuelve el estado del
        sello, la huella, la fecha, el anclaje en Bitcoin y la licencia declarada. No expone datos
        personales del registrante.
      security: []
      parameters:
        - name: slug
          in: path
          required: true
          description: Identificador público del certificado.
          schema:
            type: string
      responses:
        "200":
          description: Datos del certificado.
          content:
            application/json:
              schema:
                type: object
                properties:
                  verified:
                    type: boolean
                  declaredTitle:
                    type: string
                  status:
                    type: string
                  technical:
                    type: object
                    properties:
                      originalHashSha256:
                        type: string
                      mimeType:
                        type: string
        "202":
          description: La obra existe pero su certificado aún se está emitiendo.
        "404":
          description: No existe ningún certificado con ese identificador.

  /verify:
    get:
      operationId: verifyByHash
      summary: Busca un certificado por la huella SHA-256 de un archivo
      description: >
        Permite comprobar si un archivo concreto ya está sellado, sin necesidad de conocer su
        identificador. Público y sin autenticación.
      security: []
      parameters:
        - name: hash
          in: query
          required: true
          description: Huella SHA-256 en hexadecimal, 64 caracteres.
          schema:
            type: string
            pattern: "^[a-fA-F0-9]{64}$"
      responses:
        "200":
          description: Certificado encontrado.
        "404":
          description: Esa huella no está registrada.

  /agent/manifest:
    get:
      operationId: getConnectorManifest
      summary: Describe el conector, sus límites y el flujo de aprobación humana
      description: >
        Úsalo antes de operar para conocer los límites vigentes y confirmar que toda certificación
        requiere aprobación humana.
      security: []
      responses:
        "200":
          description: Manifiesto del conector.

  /agent/works/draft:
    post:
      operationId: createDraft
      summary: Crea un BORRADOR de certificación (no emite certificado)
      description: >
        Crea un borrador que queda a la espera de que el titular de la clave lo apruebe desde su
        panel. NO emite ningún certificado y NO ancla nada en Bitcoin hasta esa aprobación.
        Después de llamar a esta operación, informa al usuario de que su obra está PENDIENTE DE
        APROBACIÓN, nunca de que ya está certificada.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [file, declaredTitle, declaredType, disclaimerVersion]
              properties:
                file:
                  type: string
                  format: binary
                  description: Archivo a sellar.
                declaredTitle:
                  type: string
                  description: Título declarado de la obra.
                declaredType:
                  type: string
                  enum: [video, image, audio, document]
                disclaimerVersion:
                  type: string
                  description: Versión del aviso legal aceptada. Usa "2026-07-28".
                authorship:
                  type: string
                  description: Declaración de autoría.
                declaredCategory:
                  type: string
                  description: Categoría de obra, por ejemplo "photography" o "software".
                rightsBasis:
                  type: string
                  description: Base de derecho, por ejemplo "own-creator".
                licenseId:
                  type: string
                  description: Licencia declarada, por ejemplo "cc-by-4.0".
                locale:
                  type: string
                  description: Idioma del certificado y de los avisos, por ejemplo "es" o "en".
      responses:
        "201":
          description: Borrador creado, pendiente de aprobación humana.
          content:
            application/json:
              schema:
                type: object
                properties:
                  workId:
                    type: string
                  status:
                    type: string
                    example: agent_draft
                  message:
                    type: string
        "401":
          description: Falta la clave, o está revocada o caducada.
        "403":
          description: La cuenta no tiene la verificación de identidad aprobada.
        "429":
          description: Se superó el límite de borradores por hora.

  /agent/works:
    get:
      operationId: listMyWorks
      summary: Lista las obras del titular de la clave
      description: >
        Devuelve estado, identificador público y estado del anclaje. Sirve para comprobar si un
        borrador ya fue aprobado y certificado.
      responses:
        "200":
          description: Listado de obras.
        "401":
          description: Clave inválida.

  /agent/works/{id}:
    get:
      operationId: getMyWork
      summary: Consulta una obra concreta del titular de la clave
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Datos de la obra.
        "404":
          description: No existe o no pertenece al titular de la clave.

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: >
        Clave de agente con formato vugc_… Se genera en Mi panel → Cuenta → Claves de agente y
        requiere tener la verificación de identidad aprobada. Se muestra una sola vez: en el
        servidor solo se guarda su hash SHA-256.
