openapi: 3.0.0
info:
  version: 2.0.0
  title: Exolink API
  contact:
    name: Exolink Support
    email: support@exolink.com
servers:
  - url: https://api.exolink.cloud
tags:
  - name: Public
    description: Public endpoints
  - name: Auth
    description: Authentication and authorization endpoints
  - name: User
    description: User management endpoints
  - name: Product
    description: Product and pricing endpoints
  - name: Static
    description: Static configuration endpoints
  - name: Tenant
    description: Tenant management endpoints
  - name: CPMS
    description: CPMS management endpoints
  - name: Charger
    description: Charger management endpoints
  - name: Lab
    description: Lab management endpoints
  - name: Logs
    description: Log endpoints
  - name: Domain
    description: Custom Domain endpoints
security:
  - bearerToken: []
paths:
  /health:
    get:
      summary: Health Check
      description: Service health monitoring endpoint
      operationId: health_check
      tags:
        - Public
      security: []
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
  /auth/signup:
    post:
      summary: User Signup
      description: Register a new user account
      operationId: auth_signup
      tags:
        - Auth
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SignupRequest'
      responses:
        '200':
          description: User registered successfully
  /auth/confirm:
    post:
      summary: Confirm User Signup
      description: Confirm user registration with verification code
      operationId: auth_confirm
      tags:
        - Auth
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmRequest'
      responses:
        '200':
          description: User confirmed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
  /auth/login:
    post:
      summary: User Login
      description: Authenticate user and return access tokens
      operationId: auth_login
      tags:
        - Auth
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Login successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
  /auth/refresh:
    post:
      summary: Refresh Access Token
      description: Get new access token using refresh token
      operationId: auth_refresh
      tags:
        - Auth
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RefreshRequest'
      responses:
        '200':
          description: Token refreshed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
  /auth/forgot:
    post:
      summary: Initiate Password Reset
      description: Send password reset code to user email
      operationId: auth_forgot
      tags:
        - Auth
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - username
              properties:
                username:
                  type: string
                  description: User's email address
      responses:
        '200':
          description: Password reset initiated
  /auth/valid:
    get:
      summary: Validate Access Token
      description: Check if the provided access token is valid
      operationId: auth_valid
      tags:
        - Auth
      responses:
        '200':
          description: Token is valid
  /user/{userId}:
    parameters:
      - in: path
        name: userId
        schema:
          type: string
        required: true
        description: User ID
    get:
      summary: Get User
      description: Retrieve user information
      operationId: get_user
      tags:
        - User
      responses:
        '200':
          description: User information
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
    put:
      summary: Update User
      description: Update user profile information
      operationId: update_user
      tags:
        - User
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: User updated successfully
    delete:
      summary: Delete User
      description: Delete user account
      operationId: delete_user
      x-hideTryItPanel: true
      tags:
        - User
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - password
              properties:
                password:
                  type: string
                  description: User password for confirmation
      responses:
        '200':
          description: User deleted successfully
  /user/{userId}/logout:
    parameters:
      - in: path
        name: userId
        schema:
          type: string
        required: true
    get:
      summary: Logout User
      description: Logout user and invalidate tokens
      operationId: user_logout
      tags:
        - User
      responses:
        '200':
          description: Logout successful
  /user/{userId}/confirm:
    parameters:
      - in: path
        name: userId
        schema:
          type: string
        required: true
    post:
      summary: Confirm MFA Setup
      description: Confirm multi-factor authentication setup
      operationId: user_confirm_mfa
      tags:
        - User
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - code
              properties:
                code:
                  type: string
                  description: MFA verification code
      responses:
        '200':
          description: MFA confirmed successfully
  /user/{userId}/settings:
    parameters:
      - in: path
        name: userId
        schema:
          type: string
        required: true
    get:
      summary: Get User Settings
      description: Retrieve user settings and preferences
      operationId: get_user_settings
      tags:
        - User
      responses:
        '200':
          description: User settings
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSettings'
    put:
      summary: Update User Settings
      description: Update user settings and preferences
      operationId: update_user_settings
      tags:
        - User
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserSettingsRequest'
      responses:
        '200':
          description: Settings updated successfully
  /user/{userId}/tenant:
    parameters:
      - in: path
        name: userId
        schema:
          type: string
        required: true
    get:
      summary: Get User Tenants
      description: List all tenants the user has access to
      operationId: get_user_tenants
      tags:
        - User
      responses:
        '200':
          description: List of user tenants
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TenantInfo'
    post:
      summary: Create Tenant
      description: Create a new tenant for the user
      operationId: create_user_tenant
      tags:
        - User
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - password
              properties:
                password:
                  type: string
                  description: User password for confirmation
      responses:
        '200':
          description: Tenant created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Tenant'
  /product:
    get:
      summary: List Products
      description: Get list of available products and pricing
      operationId: list_products
      tags:
        - Product
      responses:
        '200':
          description: List of products
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Product'
  /product/{productId}:
    parameters:
      - in: path
        name: productId
        schema:
          type: integer
        required: true
    get:
      summary: Get Product
      description: Get details of a specific product
      operationId: get_product
      tags:
        - Product
      responses:
        '200':
          description: Product details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
  /tenant/{tenant}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
        description: Tenant domain prefix
    get:
      summary: Get Tenant
      description: Retrieve tenant information
      operationId: get_tenant
      tags:
        - Tenant
      responses:
        '200':
          description: Tenant information
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Tenant'
    put:
      summary: Update Tenant
      description: Update tenant information
      operationId: update_tenant
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Tenant name
      responses:
        '200':
          description: Tenant updated successfully
  /tenant/{tenant}/stats:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Tenant Statistics
      description: Retrieve tenant usage statistics
      operationId: get_tenant_stats
      tags:
        - Tenant
      responses:
        '200':
          description: Tenant statistics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantStats'
  /tenant/{tenant}/initialize:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
  /tenant/{tenant}/subscription:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Subscription
      description: Retrieve tenant subscription information
      operationId: get_tenant_subscription
      tags:
        - Tenant
      responses:
        '200':
          description: Subscription information
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Subscription'
  /tenant/{tenant}/mail:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
  /tenant/{tenant}/user:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: List Tenant Users
      description: Get list of users in the tenant
      operationId: list_tenant_users
      tags:
        - Tenant
      responses:
        '200':
          description: List of tenant users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TenantUser'
    put:
      summary: Bulk Set User Roles
      description: Set roles for multiple users
      operationId: bulk_set_user_roles
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                    description: User ID
                  role:
                    type: string
                    description: User role
      responses:
        '200':
          description: Roles updated successfully
  /tenant/{tenant}/user/{userId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: userId
        schema:
          type: string
        required: true
    put:
      summary: Set User Role
      description: Set role for a specific user
      operationId: set_user_role
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - role
              properties:
                role:
                  type: string
                  description: User role
      responses:
        '200':
          description: Role updated successfully
    delete:
      summary: Remove User from Tenant
      description: Remove user from the tenant
      operationId: remove_tenant_user
      tags:
        - Tenant
      responses:
        '200':
          description: User removed successfully
  /tenant/{tenant}/invite:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    post:
      summary: Create Invite
      description: Create invitation for new tenant user
      operationId: create_tenant_invite
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateInviteRequest'
      responses:
        '200':
          description: Invitation created successfully
  /tenant/{tenant}/charger:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: List Chargers
      description: Return the list of chargers for the given tenant
      operationId: list_chargers
      tags:
        - Charger
      responses:
        '200':
          description: List of chargers
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Charger'
              examples:
                OK:
                  summary: OK
                  value:
                    $ref: '#/components/examples/ChargerList'
    post:
      summary: Create Charger
      description: Create a new charger
      operationId: create_charger
      tags:
        - Charger
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateChargerRequest'
      responses:
        '200':
          description: Charger created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Charger'
    put:
      summary: Batch Update Chargers
      description: Update multiple chargers at once
      operationId: batch_update_chargers
      tags:
        - Charger
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      displayName:
                        type: string
                - type: object
                  properties:
                    chargerIds:
                      type: array
                      items:
                        type: integer
                    displayName:
                      type: string
      responses:
        '200':
          description: Chargers updated successfully
  /tenant/{tenant}/charger/{chargerId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: chargerId
        schema:
          type: integer
        required: true
    get:
      summary: Get Charger
      description: Get details of a specific charger
      operationId: get_charger
      tags:
        - Charger
      responses:
        '200':
          description: Charger details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Charger'
    put:
      summary: Update Charger
      description: Update charger information
      operationId: update_charger
      tags:
        - Charger
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                displayName:
                  type: string
                  description: Charger display name
      responses:
        '200':
          description: Charger updated successfully
    delete:
      summary: Delete Charger
      description: Delete a charger
      operationId: delete_charger
      tags:
        - Charger
      responses:
        '200':
          description: Charger deleted successfully
    patch:
      summary: Send Charger Action
      description: Send action command to charger
      operationId: send_charger_action
      tags:
        - Charger
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - action
              properties:
                action:
                  type: string
                  description: Action command
                data:
                  type: object
                  description: Action data
      responses:
        '200':
          description: Action sent successfully
  /tenant/{tenant}/charger/{chargerId}/status:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: chargerId
        schema:
          type: integer
        required: true
    get:
      summary: Get Charger Status
      description: Get real-time status of a charger
      operationId: get_charger_status
      tags:
        - Charger
      responses:
        '200':
          description: Charger status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChargerStatus'
  /tenant/{tenant}/cpms:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: List CPMS
      description: Return the list of CPMS for the given tenant
      operationId: list_cpms
      tags:
        - CPMS
      responses:
        '200':
          description: List of CPMS
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CPMS'
              examples:
                OK:
                  summary: OK
                  value:
                    $ref: '#/components/examples/CPMSList'
    post:
      summary: Create CPMS
      description: Create a new CPMS backend
      operationId: create_cpms
      tags:
        - CPMS
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCPMSRequest'
      responses:
        '200':
          description: CPMS created successfully
  /tenant/{tenant}/cpms/{cpmsId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: cpmsId
        schema:
          type: integer
        required: true
    get:
      summary: Get CPMS
      description: Get details of a specific CPMS backend
      operationId: get_cpms
      tags:
        - CPMS
      responses:
        '200':
          description: CPMS details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CPMS'
    put:
      summary: Update CPMS
      description: Update CPMS backend information
      operationId: update_cpms
      tags:
        - CPMS
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  description: CPMS WebSocket URL
      responses:
        '200':
          description: CPMS updated successfully
    delete:
      summary: Delete CPMS
      description: Delete a CPMS backend
      operationId: delete_cpms
      tags:
        - CPMS
      responses:
        '200':
          description: CPMS deleted successfully
  /tenant/{tenant}/ips:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: List IPs
      description: Get IP whitelist for the tenant
      operationId: list_tenant_ips
      tags:
        - Tenant
      responses:
        '200':
          description: List of whitelisted IPs
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TenantIP'
    post:
      summary: Add IP
      description: Add IP to whitelist
      operationId: add_tenant_ip
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - ip
              properties:
                ip:
                  type: string
                  description: IP address in CIDR notation
                  example: 123.123.123.123/10
      responses:
        '200':
          description: IP added successfully
  /tenant/{tenant}/ips/{ipId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: ipId
        schema:
          type: integer
        required: true
    delete:
      summary: Delete IP
      description: Remove IP from whitelist
      operationId: delete_tenant_ip
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - ips
              properties:
                ips:
                  type: array
                  items:
                    type: string
                  description: List of IPs to delete
      responses:
        '200':
          description: IP deleted successfully
  /tenant/{tenant}/metrics:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Metrics
      description: Get tenant usage metrics
      operationId: get_tenant_metrics
      tags:
        - Tenant
      responses:
        '200':
          description: Tenant metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantMetrics'
  /tenant/{tenant}/profile:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: List Profiles
      description: Get list of charger configuration profiles
      operationId: list_profiles
      tags:
        - Tenant
      responses:
        '200':
          description: List of profiles
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Profile'
    post:
      summary: Create Profile
      description: Create a new configuration profile
      operationId: create_profile
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProfileRequest'
      responses:
        '200':
          description: Profile created successfully
  /tenant/{tenant}/profile/{profileId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: profileId
        schema:
          type: integer
        required: true
    get:
      summary: Get Profile
      description: Get details of a specific profile
      operationId: get_profile
      tags:
        - Tenant
      responses:
        '200':
          description: Profile details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profile'
    put:
      summary: Update Profile
      description: Update profile information
      operationId: update_profile
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                displayName:
                  type: string
                cpmsId:
                  type: integer
      responses:
        '200':
          description: Profile updated successfully
    delete:
      summary: Delete Profile
      description: Delete a configuration profile
      operationId: delete_profile
      tags:
        - Tenant
      responses:
        '200':
          description: Profile deleted successfully
  /tenant/{tenant}/provision:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Provision Status
      description: Get current provisioning status
      operationId: get_provision_status
      tags:
        - Tenant
      responses:
        '200':
          description: Provision status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProvisionStatus'
    post:
      summary: Start Provisioning
      description: Start charger provisioning mode
      operationId: start_provisioning
      tags:
        - Tenant
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - profileId
                - duration
              properties:
                profileId:
                  type: integer
                  description: Profile ID for provisioning
                duration:
                  type: integer
                  description: Provisioning duration in minutes
      responses:
        '200':
          description: Provisioning started
    delete:
      summary: Stop Provisioning
      description: Stop charger provisioning mode
      operationId: stop_provisioning
      tags:
        - Tenant
      responses:
        '200':
          description: Provisioning stopped
  /tenant/{tenant}/domain:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Domain
      description: Get custom domain configuration
      operationId: get_tenant_domain
      tags:
        - Domain
      responses:
        '200':
          description: Domain configuration
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Domain'
    post:
      summary: Create Domain
      description: Configure custom domain for tenant
      operationId: create_tenant_domain
      tags:
        - Domain
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - domain
              properties:
                domain:
                  type: string
                  description: Custom domain name
      responses:
        '200':
          description: Domain created successfully
    delete:
      summary: Delete Domain
      description: Remove custom domain configuration
      operationId: delete_tenant_domain
      tags:
        - Domain
      responses:
        '200':
          description: Domain deleted successfully
  /tenant/{tenant}/lab:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: List Labs
      description: Get list of lab environments
      operationId: list_labs
      tags:
        - Lab
      responses:
        '200':
          description: List of labs
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Lab'
    post:
      summary: Create Lab
      description: Create a new lab environment
      operationId: create_lab
      tags:
        - Lab
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - displayName
              properties:
                displayName:
                  type: string
                  description: Lab display name
      responses:
        '200':
          description: Lab created successfully
  /tenant/{tenant}/lab/{labId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: labId
        schema:
          type: integer
        required: true
    put:
      summary: Update Lab
      description: Update lab information
      operationId: update_lab
      tags:
        - Lab
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                displayName:
                  type: string
      responses:
        '200':
          description: Lab updated successfully
    patch:
      summary: Update Lab Task
      description: Update lab task configuration
      operationId: update_lab_task
      tags:
        - Lab
      responses:
        '200':
          description: Task updated successfully
    delete:
      summary: Delete Lab
      description: Delete a lab environment
      operationId: delete_lab
      tags:
        - Lab
      responses:
        '200':
          description: Lab deleted successfully
  /tenant/{tenant}/lab/{labId}/config:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: labId
        schema:
          type: integer
        required: true
    get:
      summary: List Config Versions
      description: Get list of lab configuration versions
      operationId: list_lab_configs
      tags:
        - Lab
      responses:
        '200':
          description: List of config versions
  /tenant/{tenant}/lab/{labId}/config/latest:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: labId
        schema:
          type: integer
        required: true
    get:
      summary: Get Latest Config
      description: Get latest lab configuration
      operationId: get_lab_config_latest
      tags:
        - Lab
      responses:
        '200':
          description: Latest configuration
  /tenant/{tenant}/lab/{labId}/config/{configId}:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
      - in: path
        name: labId
        schema:
          type: integer
        required: true
      - in: path
        name: configId
        schema:
          type: string
        required: true
    get:
      summary: Get Config Version
      description: Get specific lab configuration version
      operationId: get_lab_config
      tags:
        - Lab
      responses:
        '200':
          description: Configuration version
  /tenant/{tenant}/lab/version:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Latest Lab Version
      description: Get latest available lab software version
      operationId: get_lab_version
      tags:
        - Lab
      responses:
        '200':
          description: Latest lab version
  /tenant/{tenant}/logs/audit:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Audit Logs
      description: Get audit logs for the tenant
      operationId: get_audit_logs
      tags:
        - Logs
      parameters:
        - in: header
          name: x-exo-from
          schema:
            type: string
            format: date-time
          description: Start date for log range
        - in: header
          name: x-exo-to
          schema:
            type: string
            format: date-time
          description: End date for log range
      responses:
        '200':
          description: Audit logs
  /tenant/{tenant}/logs/ocpp:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get OCPP Logs
      description: Get OCPP communication logs
      operationId: get_ocpp_logs
      tags:
        - Logs
      parameters:
        - in: header
          name: x-exo-from
          schema:
            type: string
            format: date-time
          description: Start date for log range
        - in: header
          name: x-exo-to
          schema:
            type: string
            format: date-time
          description: End date for log range
        - in: header
          name: Content-Type
          schema:
            type: string
            enum:
              - text/csv
          description: Response format (CSV)
      responses:
        '200':
          description: OCPP logs
          content:
            text/csv:
              schema:
                type: string
  /tenant/{tenant}/billing:
    parameters:
      - in: path
        name: tenant
        schema:
          type: string
        required: true
    get:
      summary: Get Billing Portal Session
      description: Get Stripe billing portal session URL
      operationId: get_billing_portal
      tags:
        - Tenant
      responses:
        '200':
          description: Billing portal session
components:
  securitySchemes:
    bearerToken:
      description: Bearer token
      type: http
      scheme: bearer
  schemas:
    SignupRequest:
      type: object
      required:
        - username
        - givenName
        - familyName
      properties:
        username:
          type: string
          description: User's email address
          format: email
          example: user@example.com
        givenName:
          type: string
          description: User's first name
          example: John
        familyName:
          type: string
          description: User's last name
          example: Doe
    ConfirmRequest:
      type: object
      required:
        - username
        - code
        - password
      properties:
        username:
          type: string
          description: User's email address
          format: email
        code:
          type: string
          description: Verification code sent to email
          example: '873858'
        password:
          type: string
          description: User's password
          format: password
    LoginRequest:
      type: object
      required:
        - username
        - password
      properties:
        username:
          type: string
          description: User's email address
          format: email
        password:
          type: string
          description: User's password
          format: password
        invitation:
          type: string
          description: Optional invitation token
        session:
          type: string
          description: MFA session token (if continuing MFA flow)
        code:
          type: string
          description: MFA verification code (if continuing MFA flow)
    RefreshRequest:
      type: object
      required:
        - refreshToken
      properties:
        refreshToken:
          type: string
          description: Refresh token from previous authentication
    AuthResponse:
      type: object
      properties:
        Token:
          type: object
          description: Authentication tokens
          properties:
            AccessToken:
              type: string
              description: JWT access token for API requests
            RefreshToken:
              type: string
              description: Token for refreshing access tokens
            IdToken:
              type: string
              description: ID token containing user identity claims
        UserInfo:
          $ref: '#/components/schemas/UserInfo'
        Settings:
          type: object
          description: User settings including default tenant
          properties:
            default:
              type: object
              properties:
                tenant:
                  type: string
                  description: Default tenant domain prefix
    UserInfo:
      type: object
      properties:
        userId:
          type: string
          description: Unique identifier for the user (UUID)
        username:
          type: string
          description: User's email address
        email:
          type: string
          description: User's email address
        givenName:
          type: string
          description: User's first name
        familyName:
          type: string
          description: User's last name
        mfa:
          type: boolean
          description: Whether multi-factor authentication is enabled
        perms:
          type: object
          description: User permissions per tenant (tenant domain prefix -> role mapping)
          additionalProperties:
            type: string
    User:
      allOf:
        - $ref: '#/components/schemas/UserInfo'
        - type: object
          properties:
            createdAt:
              type: string
              format: date-time
              description: When the user account was created
            updatedAt:
              type: string
              format: date-time
              description: When the user account was last updated
    UpdateUserRequest:
      type: object
      properties:
        givenName:
          type: string
          description: User's first name
        familyName:
          type: string
          description: User's last name
        email:
          type: string
          format: email
          description: User's email address
        oldPassword:
          type: string
          format: password
          description: Current password (required for password change)
        newPassword:
          type: string
          format: password
          description: New password
        mfa:
          type: boolean
          description: Enable or disable multi-factor authentication
        password:
          type: string
          format: password
          description: Password for MFA changes
    UserSettings:
      type: object
      properties:
        language:
          type: string
          description: Preferred language code (e.g., en, de)
          example: en
        region:
          type: string
          description: Preferred region code
          example: US
        defaultTenant:
          type: string
          description: Default tenant domain prefix
        default:
          type: object
          description: Default settings object
          properties:
            tenant:
              type: string
              description: Default tenant domain prefix
    UpdateUserSettingsRequest:
      type: object
      properties:
        language:
          type: string
          description: Preferred language code
        region:
          type: string
          description: Preferred region code
        defaultTenant:
          type: string
          description: Default tenant domain prefix
    Tenant:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the tenant
          example: 1
        name:
          type: string
          description: Tenant display name
          example: My Company
        domainPrefix:
          type: string
          description: Unique domain prefix for the tenant (used in URLs and subdomains)
          example: abc123
        stripeCustomerId:
          type: string
          description: Stripe customer ID for billing
        connectUrl:
          type: string
          description: WebSocket connection URL for IoT/OCPP
          example: wss://abc123.broker.exolink.cloud/
        customDomain:
          type: string
          description: Custom domain WebSocket URL (if configured)
          example: wss://chargers.company.com/
        createdAt:
          type: string
          format: date-time
          description: When the tenant was created
        updatedAt:
          type: string
          format: date-time
          description: When the tenant was last updated
        deletedAt:
          type: string
          format: date-time
          description: When the tenant was deleted (null if active)
    TenantInfo:
      type: object
      description: Simplified tenant information for user tenant list
      properties:
        id:
          type: integer
          description: Tenant ID
        name:
          type: string
          description: Tenant name
        domainPrefix:
          type: string
          description: Tenant domain prefix
        role:
          type: string
          description: User's role in this tenant
          enum:
            - admin
            - user
            - viewer
    TenantStats:
      type: object
      description: Tenant usage statistics
      properties:
        chargerCount:
          type: integer
          description: Total number of chargers
        activeChargers:
          type: integer
          description: Number of currently connected chargers
        totalUsers:
          type: integer
          description: Number of users in the tenant
        messageCount:
          type: integer
          description: Total OCPP messages processed
    TenantUser:
      type: object
      description: User information within a tenant context
      properties:
        userId:
          type: string
          description: User ID
        username:
          type: string
          description: User email
        givenName:
          type: string
          description: User's first name
        familyName:
          type: string
          description: User's last name
        role:
          type: string
          description: User's role in the tenant
          enum:
            - admin
            - user
            - viewer
    Subscription:
      type: object
      description: Tenant subscription information
      properties:
        id:
          type: integer
          description: Subscription ID
        tenantId:
          type: integer
          description: Tenant ID
        productId:
          type: integer
          description: Product ID
        productName:
          type: string
          description: Product name
        status:
          type: string
          description: Subscription status
          enum:
            - active
            - canceled
            - expired
        quantity:
          type: integer
          description: Subscription quantity
        stripeSubscriptionId:
          type: string
          description: Stripe subscription ID
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    Product:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the product
          example: 1
        name:
          type: string
          description: Internal product name
          example: connect_basic
        displayName:
          type: string
          description: Display name for the product
          example: Connect Basic
        description:
          type: string
          description: Product description
        active:
          type: boolean
          description: Whether the product is currently active and available for purchase
        price:
          type: integer
          description: Price in cents
          example: 2900
        stripeProductId:
          type: string
          description: Stripe product ID
        stripePriceId:
          type: string
          description: Stripe price ID
        metadata:
          type: object
          description: Product metadata including type, limits, and features
          properties:
            type:
              type: string
              enum:
                - addon
                - connect
              description: Product type (addon or connect subscription)
            active:
              type: string
              enum:
                - 'true'
                - 'false'
            icon:
              type: string
              description: Icon identifier for UI
            translation:
              type: string
              description: Translation key for product name
            limit:
              type: string
              description: Usage limit for the product
            chargerLimit:
              type: string
              description: Maximum number of chargers allowed (empty = unlimited)
            allowPromotion:
              type: string
              enum:
                - 'true'
                - 'false'
              description: Whether promotion codes can be applied
            freePeriod:
              type: string
              enum:
                - 'true'
                - 'false'
              description: Whether product can be used without booking (trial period)
            ribbon:
              type: string
              enum:
                - 'true'
                - 'false'
              description: Show special offer ribbon in UI
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    Profile:
      type: object
      description: Charger configuration profile
      properties:
        id:
          type: integer
          description: Profile ID
          example: 1
        tenantId:
          type: integer
          description: Tenant ID
        displayName:
          type: string
          description: Profile display name
          example: Default Profile
        dynamic:
          type: boolean
          description: Whether this is a dynamically generated profile
          default: false
        cpmsId:
          type: integer
          description: Associated CPMS backend ID
        cpmsName:
          type: string
          description: Associated CPMS backend name
        cpmsUrl:
          type: string
          description: Associated CPMS backend URL
        labId:
          type: integer
          description: Associated lab environment ID (if applicable)
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        deletedAt:
          type: string
          format: date-time
    CreateProfileRequest:
      type: object
      required:
        - displayName
        - cpmsId
      properties:
        displayName:
          type: string
          description: Profile display name
        cpmsId:
          type: integer
          description: CPMS backend ID to associate with this profile
    Lab:
      type: object
      description: Lab environment for testing and development
      properties:
        id:
          type: integer
          description: Lab ID
        tenantId:
          type: integer
          description: Tenant ID
        displayName:
          type: string
          description: Lab display name
        initialProfileId:
          type: integer
          description: Initial profile ID for the lab
        version:
          type: string
          description: Lab software version
        tenantSubscriptionId:
          type: integer
          description: Associated subscription ID
        health:
          type: string
          description: Lab health status
        status:
          type: string
          description: Lab status
          enum:
            - READY
            - PENDING
        url:
          type: string
          description: Lab access URL
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        deletedAt:
          type: string
          format: date-time
    Domain:
      type: object
      description: Custom domain configuration
      properties:
        id:
          type: integer
          description: Domain ID
        tenantId:
          type: integer
          description: Tenant ID
        domainName:
          type: string
          description: Custom domain name
          example: chargers.company.com
        state:
          type: string
          description: Domain verification and setup state
          enum:
            - PENDING
            - VERIFYING
            - COMPLETE
            - FAILED
        verificationRecord:
          type: string
          description: DNS verification record
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    ProvisionStatus:
      type: object
      description: Charger provisioning status
      properties:
        active:
          type: boolean
          description: Whether provisioning mode is currently active
        profileId:
          type: integer
          description: Profile ID used for provisioning
        expiresAt:
          type: string
          format: date-time
          description: When provisioning mode expires
    TenantIP:
      type: object
      description: IP whitelist entry
      properties:
        id:
          type: integer
          description: IP entry ID
        tenantId:
          type: integer
          description: Tenant ID
        ip:
          type: string
          description: IP address in CIDR notation
          example: 123.123.123.123/10
        createdAt:
          type: string
          format: date-time
    TenantMetrics:
      type: object
      description: Tenant usage and performance metrics
      properties:
        messageCount:
          type: integer
          description: Total OCPP messages processed
        chargerCount:
          type: integer
          description: Total number of chargers
        activeConnections:
          type: integer
          description: Currently active charger connections
        dataTransferred:
          type: integer
          description: Total data transferred in bytes
    CreateInviteRequest:
      type: object
      required:
        - receiver
        - role
        - language
      properties:
        receiver:
          type: string
          format: email
          description: Email address of the person to invite
        role:
          type: string
          description: Role to assign to the invited user
          enum:
            - admin
            - user
            - viewer
        language:
          type: string
          description: Language for the invitation email
          example: en
    CreateChargerRequest:
      type: object
      required:
        - profileId
        - displayName
        - identity
        - chargePointModel
        - chargePointVendor
      properties:
        profileId:
          type: integer
          description: Configuration profile ID
        displayName:
          type: string
          description: Charger display name
        identity:
          type: string
          description: Unique identity for OCPP communication
        provisioned:
          type: boolean
          description: Whether charger is pre-provisioned
          default: false
        chargeBoxSerialNumber:
          type: string
          description: Charge box serial number
        chargePointSerialNumber:
          type: string
          description: Charge point serial number
        meterSerialNumber:
          type: string
          description: Meter serial number
        chargePointModel:
          type: string
          description: Charge point model
        chargePointVendor:
          type: string
          description: Charge point vendor
        firmwareVersion:
          type: string
          description: Firmware version
        iccid:
          type: string
          description: SIM card ICCID
        imsi:
          type: string
          description: SIM card IMSI
        meterType:
          type: string
          description: Meter type
    ChargerStatus:
      type: object
      description: Real-time charger status information
      properties:
        connected:
          type: boolean
          description: Whether charger is currently connected
        lastSeen:
          type: string
          format: date-time
          description: Last connection time
        status:
          type: string
          description: Current OCPP ChargePointStatus
          enum:
            - Available
            - Preparing
            - Charging
            - SuspendedEVSE
            - SuspendedEV
            - Finishing
            - Reserved
            - Unavailable
            - Faulted
        errorCode:
          type: string
          description: OCPP error code if status is Faulted
        connectors:
          type: array
          description: Status of individual connectors
          items:
            type: object
            properties:
              connectorId:
                type: integer
                description: >-
                  Connector ID (0 for main charger, 1+ for individual
                  connectors)
              status:
                type: string
                description: OCPP connector status
                enum:
                  - Available
                  - Preparing
                  - Charging
                  - SuspendedEVSE
                  - SuspendedEV
                  - Finishing
                  - Reserved
                  - Unavailable
                  - Faulted
              currentPower:
                type: number
                description: Current power output in kW
    CreateCPMSRequest:
      type: object
      required:
        - displayName
        - url
        - interval
      properties:
        displayName:
          type: string
          description: CPMS backend display name
        url:
          type: string
          format: uri
          description: WebSocket URL for CPMS backend
          example: wss://cpms.example.com
        interval:
          type: integer
          description: Heartbeat interval in seconds
          example: 30
    Charger:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the charger
          example: 1
        tenantId:
          type: integer
          description: ID of the tenant that owns this charger
          example: 1
        profileId:
          type: integer
          description: ID of the configuration profile associated with this charger
          example: 1
        displayName:
          type: string
          description: User-friendly name for the charger
          example: My Charger
        provisioned:
          type: boolean
          description: Indicates whether the charger has been provisioned and configured
          example: false
          default: false
        identity:
          type: string
          description: Unique identity string used for OCPP communication
          example: TEST
        chargeBoxSerialNumber:
          type: string
          description: Serial number of the charge box hardware
          example: 12345
        chargePointSerialNumber:
          type: string
          description: Serial number of the charge point
          example: 12345
        meterSerialNumber:
          type: string
          description: Serial number of the integrated energy meter
        chargePointModel:
          type: string
          description: Model identifier of the charge point
          example: KC-P30-EC2404B2-E00
        chargePointVendor:
          type: string
          description: Manufacturer or vendor of the charge point
          example: Keba AG
        firmwareVersion:
          type: string
          description: Current firmware version running on the charger
          example: 1.0.0
        iccid:
          type: string
          description: Integrated Circuit Card Identifier for the SIM card (if applicable)
        imsi:
          type: string
          description: >-
            International Mobile Subscriber Identity for cellular connectivity
            (if applicable)
        meterType:
          type: string
          description: Type or model of the energy meter
        status:
          description: Current operational status of the charger
          enum:
            - BLOCKED
            - NONE
        createdAt:
          type: string
          description: Timestamp when the charger record was created
          example: '2025-10-15T15:19:50.834Z'
        updatedAt:
          type: string
          description: Timestamp when the charger record was last updated
          example: '2025-10-15T15:19:50.834Z'
        deletedAt:
          type: string
          description: Timestamp when the charger record was soft-deleted (null if active)
          example: '2025-10-15T15:19:50.834Z'
        profileName:
          type: string
          description: Name of the configuration profile associated with this charger
          example: Loadtest Profile
        chargerConnected:
          type: boolean
          description: Indicates whether the charger is currently connected to the platform
        cpmsConnected:
          type: boolean
          description: >-
            Indicates whether the charger is currently connected to the CPMS
            backend
        cpmsName:
          type: string
          description: Name of the CPMS backend this charger is connected to
          example: MyCPMS
        cpmsUrl:
          type: string
          description: WebSocket URL of the CPMS backend this charger is connected to
          example: wss://cpms.exolink.com
    CPMS:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the CPMS backend
          example: 1
        tenantId:
          type: integer
          description: ID of the tenant that owns this CPMS backend
          example: 1
        displayName:
          type: string
          description: User-friendly name for the CPMS backend
          example: My Charger
        url:
          type: string
          description: WebSocket URL endpoint for the CPMS backend connection
          example: ws://cpms.exolink.com
        authPassThrough:
          type: boolean
          description: >-
            Indicates whether authentication credentials are passed through to
            the CPMS backend
          example: true
        interval:
          type: number
          description: Heartbeat or connection check interval in seconds
          example: 30
        createdAt:
          type: string
          description: Timestamp when the CPMS backend record was created
          example: '2025-10-15T15:19:50.834Z'
        updatedAt:
          type: string
          description: Timestamp when the CPMS backend record was last updated
          example: '2025-10-15T15:19:50.834Z'
        deletedAt:
          type: string
          description: >-
            Timestamp when the CPMS backend record was soft-deleted (null if
            active)
          example: '2025-10-15T15:19:50.834Z'
x-readme:
  explorer-enabled: true
  proxy-enabled: true
