openapi: "3.0.3"
info:
  title: Visage Labs B2B API
  version: "1.0.0"
  description: >
    Verify AI likeness licenses, browse consented model rosters,
    track usage events, and integrate rights compliance into your
    production pipeline.
  contact:
    name: Visage Labs Support
    email: support@visagelabs.net

servers:
  - url: https://visagelabs.net/api
    description: Production

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >
        Organisation-scoped API key. Obtain from Buyer Dashboard →
        Settings → API & Developer. Prefix: vsg_live_ or vsg_test_.

  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          example: "Invalid API key"
        request_id:
          type: string
          format: uuid

    PaginationMeta:
      type: object
      properties:
        total:
          type: integer
          example: 42
        limit:
          type: integer
          example: 20
        offset:
          type: integer
          example: 0
        request_id:
          type: string
          format: uuid

    RightsSummary:
      type: object
      properties:
        media_types:
          type: array
          items:
            type: string
          example: ["digital", "social"]
        channels:
          type: array
          items:
            type: string
          example: ["web", "social_media"]
        geography:
          type: string
          example: "worldwide"
        duration:
          type: string
          example: "12 months"
        derivatives_allowed:
          type: boolean
        synthetic_reuse_allowed:
          type: boolean
        training_allowed:
          type: boolean
        training_scope:
          type: string
          nullable: true
        political_allowed:
          type: boolean
        adult_allowed:
          type: boolean
        competitor_exclusion:
          type: string
          nullable: true

    LicenseVerifyResponse:
      type: object
      properties:
        status:
          type: string
          enum: [ACTIVE, REVOKED]
          example: ACTIVE
        license_key:
          type: string
          example: "VSG-A1B2-C3D4-E5F6"
        issued_at:
          type: string
          format: date-time
        deal_created_at:
          type: string
          format: date-time
        buyer_org_name:
          type: string
          example: "Acme Studios"
        talent_name:
          type: string
          example: "Alex Johnson"
        model_id:
          type: string
          format: uuid
          nullable: true
        agency_id:
          type: string
          format: uuid
          nullable: true
        model_sku:
          type: string
          nullable: true
          example: "VSG-MDL-ALEX-042"
        rights_summary:
          $ref: "#/components/schemas/RightsSummary"
        request_id:
          type: string
          format: uuid

    Model:
      type: object
      properties:
        id:
          type: string
          format: uuid
        display_name:
          type: string
        verified:
          type: boolean
        allowed_media:
          type: array
          items:
            type: string
        pricing_per_job:
          type: number
          nullable: true
        sku:
          type: string
          nullable: true
          example: "VSG-MDL-ALEX-042"
        base_rate_usd:
          type: number
          nullable: true

    License:
      type: object
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          example: "active"
        start_at:
          type: string
          format: date-time
        end_at:
          type: string
          format: date-time
        flat_fee:
          type: number
        deal_id:
          type: string
          format: uuid
        created_at:
          type: string
          format: date-time

    Deal:
      type: object
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          example: "completed"
        buyer_org_name:
          type: string
          example: "Acme Studios"
        talent_display_name:
          type: string
          example: "Alex Johnson"
        created_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
          nullable: true

    UsageEventRequest:
      type: object
      required:
        - platform_id
        - event_type
      properties:
        license_key:
          type: string
          description: "License key (VSG-XXXX-XXXX-XXXX). Use this or license_id."
          example: "VSG-A1B2-C3D4-E5F6"
        license_id:
          type: string
          format: uuid
          description: "License UUID. Alternative to license_key."
        platform_id:
          type: string
          description: "Platform identifier"
          example: "ai-video-platform"
        event_type:
          type: string
          enum: [generation, deployment, preview]
          example: "generation"
        model_id:
          type: string
          format: uuid
          description: "Licensed model UUID"
        asset_id:
          type: string
          description: "Asset ID for per-asset tracking"
          example: "VA-550e8400-e29b-41d4-a716-446655440000"
        units:
          type: integer
          default: 1
          description: "Usage units"
        timestamp:
          type: string
          format: date-time
          description: "Event timestamp (defaults to server time)"
        metadata:
          type: object
          additionalProperties: true
          description: "Free-form tracking data"
          example:
            campaign: "Summer 2026"
            format: "video"

    UsageEventResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
        license_id:
          type: string
          format: uuid
        units:
          type: integer
        platform_id:
          type: string
          nullable: true
        event_type:
          type: string
        model_id:
          type: string
          format: uuid
          nullable: true
        asset_id:
          type: string
          nullable: true
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
          format: date-time

paths:
  /b2b-v1-verify-license:
    get:
      operationId: verifyLicense
      summary: Verify a license key
      description: >
        Check if a license key is valid and active. Returns status,
        issue date, talent info, and full rights summary.
      parameters:
        - name: license_key
          in: query
          required: true
          schema:
            type: string
          example: "VSG-A1B2-C3D4-E5F6"
          description: "The license key to verify"
      responses:
        "200":
          description: License is active
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LicenseVerifyResponse"
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: License revoked or org not approved
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: License key not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /b2b-v1-models:
    get:
      operationId: listModels
      summary: List available models
      description: >
        Paginated list of AI model profiles available for licensing.
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: Paginated list of models
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Model"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /b2b-v1-licenses:
    get:
      operationId: listLicenses
      summary: List licenses
      description: >
        All licenses issued to your organisation. For compliance and audit.
      parameters:
        - name: status
          in: query
          schema:
            type: string
          description: "Filter by status (e.g. 'active')"
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: Paginated list of licenses
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/License"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /b2b-v1-deals:
    get:
      operationId: listDeals
      summary: List deals
      description: >
        All deals for your organisation. Sync into CRMs or reporting tools.
      parameters:
        - name: status
          in: query
          schema:
            type: string
          description: "Filter by deal status"
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: Paginated list of deals
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Deal"
                  meta:
                    $ref: "#/components/schemas/PaginationMeta"
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /b2b-v1-usage-event:
    post:
      operationId: logUsageEvent
      summary: Log a usage event
      description: >
        Record a generation, deployment, or preview event against a
        license for metered billing, royalty tracking, and audit trails.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UsageEventRequest"
      responses:
        "201":
          description: Usage event recorded
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/UsageEventResponse"
                  meta:
                    type: object
                    properties:
                      request_id:
                        type: string
                        format: uuid
        "400":
          description: Missing required fields
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: License not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
