openapi: 3.0.3
info:
  title: VIESAC API
  version: "1.0.0"
  description: |
    Authenticated REST API for EU VAT validation audits, certificates, and account usage.

    **Base path:** `/api/v1`

    **Authentication:** HTTP header `Authorization: Bearer <your_api_key>` on every request.
    Obtain API keys from the VIESAC dashboard after registration (`/app`).

    Human-readable documentation: https://viesac.eu/api-docs

    Rate limits apply (e.g. FREE plan for validate endpoint); see API docs for details.
  contact:
    url: https://viesac.eu/api-docs
  license:
    name: Proprietary
    url: https://viesac.eu/terms-of-service

servers:
  - url: https://viesac.eu
    description: Production

tags:
  - name: Validate
    description: Quick VAT status without creating an audit
  - name: Account
    description: Plan and usage
  - name: Audits
    description: VAT audits (VIES records) and certificates
  - name: Partners
    description: Search your saved audits by VAT or company name

security:
  - bearerAuth: []

paths:
  /api/v1/validate:
    get:
      tags: [Validate]
      summary: Validate VAT (no audit)
      description: |
        Returns `valid`, `invalid`, or `audit_required` / error. Uses the same validation chain
        as the public product (cache, VIES, optional AI) without persisting a new audit.
      parameters:
        - name: vat
          in: query
          required: true
          schema:
            type: string
          description: Full VAT identifier (e.g. DE123456789 or country + number)
      responses:
        "200":
          description: valid or invalid
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/ValidateValid"
                  - $ref: "#/components/schemas/ValidateInvalid"
        "422":
          description: Invalid input or validation error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorBody"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/v1/account:
    get:
      tags: [Account]
      summary: Account and usage
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/v1/audits:
    get:
      tags: [Audits]
      summary: List audits
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 100
            maximum: 500
        - name: date_from
          in: query
          schema:
            type: string
            format: date
        - name: date_to
          in: query
          schema:
            type: string
            format: date
        - name: vat_number
          in: query
          schema:
            type: string
        - name: order_number
          in: query
          schema:
            type: string
        - name: invoice_number
          in: query
          schema:
            type: string
        - name: country_code
          in: query
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Audit"
                  count:
                    type: integer
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      tags: [Audits]
      summary: Create audit
      description: |
        Creates a VAT validation audit (VIES pipeline, optional monitoring).
        `country_code` optional if `vat_number` includes a valid country prefix.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AuditCreate"
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Audit"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: Quota / plan limit
        "422":
          description: Validation error

  /api/v1/audits/{reference_number}:
    parameters:
      - $ref: "#/components/parameters/ReferenceNumber"
    get:
      tags: [Audits]
      summary: Get audit by reference
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Audit"
        "404":
          $ref: "#/components/responses/NotFound"
        "401":
          $ref: "#/components/responses/Unauthorized"

    put:
      tags: [Audits]
      summary: Update audit metadata
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                order_number:
                  type: string
                  nullable: true
                invoice_number:
                  type: string
                  nullable: true
                comment:
                  type: string
                  nullable: true
                monitoring:
                  type: string
                  nullable: true
                  description: "day|week|month|quarter|year or false to disable"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Audit"
        "404":
          $ref: "#/components/responses/NotFound"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/v1/audits/{reference_number}/certificate:
    parameters:
      - $ref: "#/components/parameters/ReferenceNumber"
      - name: locale
        in: query
        schema:
          type: string
          default: en
        description: PDF locale (must match app-supported locales)
    get:
      tags: [Audits]
      summary: Download PDF certificate
      description: Only when audit status is valid and certificate exists.
      responses:
        "200":
          description: PDF binary
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "404":
          $ref: "#/components/responses/NotFound"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/v1/audits/{reference_number}/certificate/xml:
    parameters:
      - $ref: "#/components/parameters/ReferenceNumber"
    get:
      tags: [Audits]
      summary: Download XML evidence
      responses:
        "200":
          description: XML
          content:
            application/xml:
              schema:
                type: string
        "404":
          $ref: "#/components/responses/NotFound"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /api/v1/partners/check:
    get:
      tags: [Partners]
      summary: Search partners in your audits
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
          description: Full VAT or company name fragment
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                  count:
                    type: integer
                  message:
                    type: string
        "401":
          $ref: "#/components/responses/Unauthorized"
        "422":
          description: Missing q

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: API key from VIESAC dashboard (Bearer token).

  parameters:
    ReferenceNumber:
      name: reference_number
      in: path
      required: true
      schema:
        type: string
      description: Audit reference number returned on create

  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorBody"
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorBody"

  schemas:
    ErrorBody:
      type: object
      properties:
        error:
          type: string
        code:
          type: string

    ValidateValid:
      type: object
      properties:
        vat:
          type: string
        country_code:
          type: string
        vat_number:
          type: string
        status:
          type: string
          enum: [valid]
        checked_at:
          type: string
          format: date-time

    ValidateInvalid:
      type: object
      properties:
        vat:
          type: string
        country_code:
          type: string
        vat_number:
          type: string
        status:
          type: string
          enum: [invalid]
        checked_at:
          type: string
          format: date-time

    Account:
      type: object
      properties:
        plan:
          type: string
        plan_label:
          type: string
        monthly_limit:
          type: integer
          nullable: true
        requests_total:
          type: integer
        requests_this_month:
          type: integer
        requests_remaining:
          type: integer
          nullable: true
        upgrade_url:
          type: string
          format: uri

    AuditCreate:
      type: object
      required: [vat_number]
      properties:
        country_code:
          type: string
          nullable: true
          minLength: 2
          maxLength: 2
        vat_number:
          type: string
        requester_vat:
          type: string
          nullable: true
        company_name:
          type: string
          nullable: true
        company_address:
          type: string
          nullable: true
        order_number:
          type: string
          nullable: true
        invoice_number:
          type: string
          nullable: true
        comment:
          type: string
          nullable: true
        method:
          type: string
          enum: [api, woocommerce, magento, make]
          nullable: true
        audit_details:
          type: object
          nullable: true
        monitoring:
          type: string
          nullable: true
          description: "day|week|month|quarter|year"

    Audit:
      type: object
      properties:
        reference_number:
          type: string
        country_code:
          type: string
        vat_number:
          type: string
        status:
          type: string
        vies:
          type: integer
          description: VIES flag as stored by the app
        company_name:
          type: string
          nullable: true
        company_address:
          type: string
          nullable: true
        consultation_number:
          type: string
          nullable: true
        requester_vat:
          type: string
          nullable: true
        order_number:
          type: string
          nullable: true
        invoice_number:
          type: string
          nullable: true
        comment:
          type: string
          nullable: true
        audit_details:
          type: object
          nullable: true
        method:
          type: string
          nullable: true
        requested_at:
          type: string
          format: date-time
          nullable: true
        certificate_url:
          type: string
          format: uri
          nullable: true
        certificate_xml_url:
          type: string
          format: uri
          nullable: true
        certificate_urls:
          type: object
          nullable: true
