openapi: 3.0.3
info:
  title: VivoxAI
  description: >
    API for creating and retrieving KYB (Know Your Business) cases and related
    resources. All KYB endpoints require Bearer authentication.
  version: 1.0.0

servers:
  - url: https://demo-api.vivox.ai
    description: Sandbox
  - url: https://portal-api.vivox.ai
    description: Production

tags:
  - name: KYB Cases
    description: >
      Endpoints for creating and retrieving KYB cases.
  - name: Users and Jurisdictions
    description: Endpoints for retrieving users within your organization and the list of supported jurisdictions.

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

  parameters:
    KybCaseId:
      in: path
      name: kyb_case_id
      description: The KYB case UUID.
      required: true
      schema:
        type: string
        format: uuid
      example: 019a51aa-6a43-7268-b9e1-3c53e8f6c8e9

  responses:
    Unauthorized:
      description: Not authenticated
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unauthorized:
              summary: Missing or invalid token
              value:
                message: Unauthenticated.
    NotFound:
      description: Resource not found or access denied
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            kybCaseNotFound:
              summary: KYB case not found
              value:
                message: "No query results for model 019a51fe-29ff-71bd-a7bb-7cf22a2d7fc0"
    ValidationError:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationErrorResponse'
          examples:
            missingJurisdiction:
              summary: Missing jurisdiction_code
              value:
                message: The jurisdiction code field is required.
                errors:
                  jurisdiction_code:
                    - The jurisdiction code field is required.

  schemas:
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
      required: [message]

    ValidationErrorResponse:
      type: object
      properties:
        message:
          type: string
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
      required: [message, errors]

    UserSummary:
      type: object
      description: Lightweight user representation.
      properties:
        id:
          type: string
          format: uuid
          example: 00a68114-e5e4-48bc-af16-bed68f2f1550
          description: The user's unique identifier.
        name:
          type: string
          example: Jane Doe
        email:
          type: string
          format: email
          example: jane@acme.com
      required: [id, name, email]

    AssignmentInput:
      type: object
      description: >
        Assign the case to an **analyst**. Provide **either** `user_id` **or** `email`.
        Use **GET /v1/users** to fetch available analysts and their IDs/emails.
        If no matching analyst is found, the request will fail with **422 Validation Error**.
      properties:
        user_id:
          type: string
          format: uuid
          description: >
            Analyst's user ID. Obtainable from **GET /v1/users** (`id` field).
          example: 2b9e2f0a-5f72-4aa1-9f2c-7b5b3ce1a2f9
        email:
          type: string
          format: email
          description: >
            Analyst's email. You may assign by email if you don't have the `user_id`.
          example: analyst@acme.com

    KybCaseStatus:
      type: string
      description: Current status of the case.
      enum: [upload_required, in_progress, completed, rejected, exited, inactive]

    KybCase:
      type: object
      description: KYB Case resource.
      properties:
        id:
          type: string
          format: uuid
          description: The KYB case UUID.
          example: 019a51fe-29ff-71bd-a7bb-7cf22a2d7fc0
        legal_name:
          type: string
          description: The legal name of the business being verified.
          example: Acme Corporation Ltd
        company_number:
          type: string
          nullable: true
          description: The official company registration number.
          example: "12345678"
        jurisdiction_code:
          type: string
          minLength: 2
          maxLength: 2
          description: Two-letter ISO country code where the company is registered.
          example: CN
        reference_id:
          type: string
          description: Your internal reference ID for tracking this case.
          example: CRM-2025-001
        website_urls:
          type: array
          description: >
            Websites associated with the business.

            **Note:** Only the **first** URL is currently analyzed and shown in the UI.
            The array format is maintained for forward compatibility.
          items:
            type: string
            format: uri
          example:
            - https://acme.com
        status:
          $ref: '#/components/schemas/KybCaseStatus'
        creator:
          $ref: '#/components/schemas/UserSummary'
        assignee:
          allOf:
            - $ref: '#/components/schemas/UserSummary'
          description: Information about the user assigned to this case. Auto-assigned to creator if not specified during creation.
        created_at:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the case was created.
          example: '2025-11-05T03:10:02.000000Z'
      required:
        - id
        - legal_name
        - jurisdiction_code
        - reference_id
        - website_urls
        - status
        - creator
        - assignee
        - created_at

    CreateKybCasePayload:
      type: object
      description: >
        Creates a KYB case
      properties:
        legal_name:
          type: string
          description: The legal name of the business. Required
          example: Acme Holdings Ltd
        company_number:
          type: string
          description: The company registration number
          example: "07495895"
        website_urls:
          type: array
          description: >
            Optional list of websites associated with the business.

            **Important:** For compatibility, this field accepts multiple URLs, but
            currently only the **first** URL in the array is processed and displayed in the
            Vivox interface. Additional URLs are ignored at this time.

            The array format is retained to allow future functionality without breaking changes.
          items:
            type: string
            format: uri
          example:
            - https://acme.com
            - https://blog.acme.com
        jurisdiction_code:
          type: string
          minLength: 2
          maxLength: 2
          description: Two-letter ISO jurisdiction code. Must exist in the jurisdictions list.
          example: CN
        reference_id:
          type: string
          description: Your internal reference key for the case.
          example: CRM-CASE-12931
        assignment:
          $ref: '#/components/schemas/AssignmentInput'
      required:
        - legal_name
        - jurisdiction_code
        - reference_id

security:
  - BearerAuth: []

paths:

  /v1/kyb-cases:
    post:
      summary: Create a new KYB case
      description: |
        **Required fields:**
        - `legal_name` - The legal name of the business
        - `jurisdiction_code` - Two-letter ISO country code (e.g., CN, US, DE)
        - `reference_id` - Your internal tracking reference

        **Assignment:** If `assignment` is not provided, the case is assigned to the creator by default.

        **Website URLs:** The API accepts multiple website URLs (`website_urls`), but currently only the **first** URL is used for analysis and displayed in the interface.
        The array format is retained for future compatibility.
      operationId: createKybCase
      tags: ['KYB Cases']
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateKybCasePayload'
            examples:
              fullExample:
                summary: Full example with all optional fields
                value:
                  legal_name: Acme Corporation Ltd
                  company_number: "12345678"
                  jurisdiction_code: CN
                  website_urls:
                    - https://acme.com
                    - https://blog.acme.com
                  reference_id: CRM-2025-001
                  assignment:
                    email: analyst@acme.com
              withAssignmentByUserId:
                summary: Case assigned immediately by user_id
                value:
                  legal_name: Acme Payments Inc
                  jurisdiction_code: US
                  reference_id: CRM-2025-001
                  assignment:
                    user_id: 2b9e2f0a-5f72-4aa1-9f2c-7b5b3ce1a2f9
      responses:
        201:
          description: Successfully created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/KybCase'
              examples:
                created:
                  summary: Standard success response
                  value:
                    data:
                      id: f3b1a5c8-8a92-4f20-bb7a-2f0f4f7a6a10
                      legal_name: Acme Holdings Ltd
                      company_number: "07495895"
                      jurisdiction_code: CN
                      reference_id: CRM-CASE-12931
                      website_urls:
                        - https://acme.com
                        - https://blog.acme.com
                      status: upload_required
                      creator:
                        id: d35a68114-e5e4-48bc-af16-bed68f2f1550
                        name: Jane Doe
                        email: jane@acme.com
                      assignee:
                        id: d35a68114-e5e4-48bc-af16-bed68f2f1550
                        name: Jane Doe
                        email: jane@acme.com
                      created_at: '2025-10-25T12:45:20.000000Z'
        401:
          $ref: '#/components/responses/Unauthorized'
        422:
          $ref: '#/components/responses/ValidationError'

  /v1/kyb-cases/{kyb_case_id}:
    parameters:
      - $ref: '#/components/parameters/KybCaseId'
    get:
      summary: Get a KYB case by ID
      operationId: getKybCaseById
      description: Retrieves detailed information about a specific KYB case.
      tags: ['KYB Cases']
      security:
        - BearerAuth: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/KybCase'
              examples:
                exampleCase:
                  summary: Example KYB case
                  value:
                    data:
                      id: 019a51fe-29ff-71bd-a7bb-7cf22a2d7fc0
                      legal_name: Acme Corporation Ltd
                      company_number: "12345678"
                      jurisdiction_code: CN
                      reference_id: CRM-2025-001
                      website_urls:
                        - https://acme.com
                      status: in_progress
                      creator:
                        id: 00a68114-e5e4-48bc-af16-bed68f2f1550
                        name: Jane Doe
                        email: jane@acme.com
                      assignee:
                        id: 954d25a4-0ec5-454e-8899-577dec5815c6
                        name: John Smith
                        email: john@acme.com
                      created_at: '2025-11-05T03:10:02.000000Z'
        401:
          $ref: '#/components/responses/Unauthorized'
        404:
          $ref: '#/components/responses/NotFound'

  /v1/users:
    get:
      summary: Returns your workspace users.
      operationId: listUsers
      tags: [Users and Jurisdictions]
      security:
        - BearerAuth: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/UserSummary'
              examples:
                sample:
                  summary: Example response
                  value:
                    - id: 00a68114-e5e4-48bc-af16-bed68f2f1550
                      name: Jane Doe
                      email: jane@acme.com
                    - id: 954d25a4-0ec5-454e-8899-577dec5815c6
                      name: John Smith
                      email: john@acme.com
        401:
          $ref: '#/components/responses/Unauthorized'

  /v1/jurisdictions:
    get:
      summary: Return the list of jurisdictions available for KYB processes.
      operationId: listJurisdictions
      tags: [Users and Jurisdictions]
      security:
        - BearerAuth: []
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    code_iso:
                      type: string
                      minLength: 2
                      maxLength: 2
                      example: CN
                    name:
                      type: string
                      example: China
                    supports_autosearch:
                      type: boolean
                      example: false
              examples:
                sample:
                  summary: Example response
                  value:
                    - code_iso: CN
                      name: China
                      supports_autosearch: false
                    - code_iso: US
                      name: United States
                      supports_autosearch: false
        401:
          $ref: '#/components/responses/Unauthorized'
