openapi: 3.1.0
info:
  title: Telematics Core Public API
  version: 1.0.0
  summary: Public gateway and connector-ingest contract for Telematics Core integrations.
  description: >
    Curated v1 API document for developers integrating Telematics Core with external
    fleet, admin, reporting, and connector systems. Bootstrap-only endpoints are
    intentionally omitted.
servers:
  - url: https://api.outlog.serv.si/api/v1
    description: Production public gateway
  - url: http://localhost:3000/api/v1
    description: Local gateway
  - url: https://ingest.outlog.serv.si
    description: Production signed ingest
tags:
  - name: Auth
  - name: Customers
  - name: Access
  - name: Vehicles
  - name: Devices
  - name: Telemetry
  - name: Reports
  - name: Connectors
  - name: Driver Mobile
  - name: Ingest
security:
  - bearerAuth: []
paths:
  /auth/login:
    post:
      operationId: authLogin
      tags: [Auth]
      security: []
      summary: Exchange user credentials for an access and refresh token bundle.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
                  format: password
      responses:
        "200":
          description: Authenticated session bundle.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AuthSessionBundle"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /auth/refresh:
    post:
      operationId: authRefresh
      tags: [Auth]
      security: []
      summary: Rotate a refresh token and return a fresh access token.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [refreshToken]
              properties:
                refreshToken:
                  type: string
      responses:
        "200":
          description: Refreshed session bundle.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AuthSessionBundle"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /auth/logout:
    post:
      operationId: authLogout
      tags: [Auth]
      summary: Revoke the current refresh session.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                refreshToken:
                  type: string
      responses:
        "204":
          description: Session revoked.
        "401":
          $ref: "#/components/responses/Unauthorized"
  /auth/me:
    get:
      operationId: authMe
      tags: [Auth]
      summary: Return current user profile, memberships, and reseller workspace context.
      parameters:
        - $ref: "#/components/parameters/ResellerIdHeader"
      responses:
        "200":
          description: Current identity context.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MeResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /customers:
    get:
      operationId: listCustomers
      tags: [Customers]
      summary: List customers visible to the authenticated user.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/ResellerIdHeader"
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PageSize"
      responses:
        "200":
          description: Customer collection.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CollectionResponse"
        "403":
          $ref: "#/components/responses/Forbidden"
    post:
      operationId: createCustomer
      tags: [Customers]
      summary: Create a customer or sub-customer.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/ResellerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerWrite"
      responses:
        "201":
          description: Customer created.
        "403":
          $ref: "#/components/responses/Forbidden"
  /customers/{customerId}:
    get:
      operationId: getCustomer
      tags: [Customers]
      summary: Get customer details.
      parameters:
        - $ref: "#/components/parameters/CustomerPath"
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Customer record.
        "404":
          $ref: "#/components/responses/NotFound"
    patch:
      operationId: updateCustomer
      tags: [Customers]
      summary: Update customer metadata, status, or reseller ownership.
      parameters:
        - $ref: "#/components/parameters/CustomerPath"
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/ResellerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerWrite"
      responses:
        "200":
          description: Customer updated.
        "403":
          $ref: "#/components/responses/Forbidden"
  /users:
    get:
      operationId: listUsers
      tags: [Access]
      summary: List users visible within the active customer.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: User collection.
        "403":
          $ref: "#/components/responses/Forbidden"
    post:
      operationId: createUser
      tags: [Access]
      summary: Create or invite a user.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserWrite"
      responses:
        "201":
          description: User created.
        "403":
          $ref: "#/components/responses/Forbidden"
  /users/{userId}:
    get:
      operationId: getUser
      tags: [Access]
      summary: Get user details and customer assignments.
      parameters:
        - $ref: "#/components/parameters/UserPath"
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: User record.
        "404":
          $ref: "#/components/responses/NotFound"
    patch:
      operationId: updateUser
      tags: [Access]
      summary: Update profile, status, or contact details.
      parameters:
        - $ref: "#/components/parameters/UserPath"
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserWrite"
      responses:
        "200":
          description: User updated.
  /roles:
    get:
      operationId: listRoles
      tags: [Access]
      summary: List global role definitions.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Role collection.
    post:
      operationId: createRole
      tags: [Access]
      summary: Create a custom global role definition. Requires platform-admin authority.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [roleKey, displayName]
              properties:
                roleKey:
                  type: string
                displayName:
                  type: string
                permissionKeys:
                  type: array
                  items:
                    type: string
      responses:
        "201":
          description: Role created.
  /permissions:
    get:
      operationId: listPermissions
      tags: [Access]
      summary: List available permission keys.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Permission collection.
  /customer-access:
    get:
      operationId: listCustomerAccess
      tags: [Access]
      summary: List active customer memberships with resolved role and permission summaries.
      responses:
        "200":
          description: Customer access summaries.
  /role-assignments:
    post:
      operationId: createRoleAssignment
      tags: [Access]
      summary: Assign a role to a user in a customer.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [userId, customerId, roleKey]
              properties:
                userId:
                  type: string
                  format: uuid
                customerId:
                  type: string
                  format: uuid
                roleKey:
                  type: string
      responses:
        "201":
          description: Role assignment created.
  /role-assignments/{roleAssignmentId}:
    delete:
      operationId: deleteRoleAssignment
      tags: [Access]
      summary: Remove a role assignment.
      parameters:
        - name: roleAssignmentId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "204":
          description: Role assignment removed.
  /vehicles:
    get:
      operationId: listVehicles
      tags: [Vehicles]
      summary: List vehicles in the active customer.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PageSize"
      responses:
        "200":
          description: Vehicle collection.
    post:
      operationId: createVehicle
      tags: [Vehicles]
      summary: Create a vehicle.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VehicleWrite"
      responses:
        "201":
          description: Vehicle created.
  /vehicles/{vehicleId}:
    get:
      operationId: getVehicle
      tags: [Vehicles]
      summary: Get vehicle detail.
      parameters:
        - $ref: "#/components/parameters/VehiclePath"
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Vehicle record.
    patch:
      operationId: updateVehicle
      tags: [Vehicles]
      summary: Update a vehicle.
      parameters:
        - $ref: "#/components/parameters/VehiclePath"
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VehicleWrite"
      responses:
        "200":
          description: Vehicle updated.
  /devices:
    get:
      operationId: listDevices
      tags: [Devices]
      summary: List devices in the active customer.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Device collection.
    post:
      operationId: createDevice
      tags: [Devices]
      summary: Register a device.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [deviceType, provider]
              properties:
                deviceType:
                  type: string
                provider:
                  type: string
                externalId:
                  type: string
      responses:
        "201":
          description: Device created.
  /vehicle-device-bindings:
    post:
      operationId: createVehicleDeviceBinding
      tags: [Devices]
      summary: Bind a device to a vehicle.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [vehicleId, deviceId]
              properties:
                vehicleId:
                  type: string
                  format: uuid
                deviceId:
                  type: string
                  format: uuid
      responses:
        "201":
          description: Binding created.
  /telemetry/gps:
    get:
      operationId: listGpsTelemetry
      tags: [Telemetry]
      summary: Query GPS points.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/VehicleIdQuery"
        - $ref: "#/components/parameters/From"
        - $ref: "#/components/parameters/To"
      responses:
        "200":
          description: GPS point collection.
  /telemetry/can:
    get:
      operationId: listCanTelemetry
      tags: [Telemetry]
      summary: Query CAN events.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/VehicleIdQuery"
        - $ref: "#/components/parameters/From"
        - $ref: "#/components/parameters/To"
      responses:
        "200":
          description: CAN event collection.
  /telemetry/tacho-events:
    get:
      operationId: listTachoEvents
      tags: [Telemetry]
      summary: Query tachograph events.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/VehicleIdQuery"
        - $ref: "#/components/parameters/From"
        - $ref: "#/components/parameters/To"
      responses:
        "200":
          description: Tachograph event collection.
  /telemetry/tacho-sessions:
    get:
      operationId: listTachoSessions
      tags: [Telemetry]
      summary: Query tachograph sessions.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/VehicleIdQuery"
        - $ref: "#/components/parameters/From"
        - $ref: "#/components/parameters/To"
      responses:
        "200":
          description: Tachograph session collection.
  /trips:
    get:
      operationId: listTrips
      tags: [Telemetry]
      summary: List calculated trips.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
        - $ref: "#/components/parameters/VehicleIdQuery"
        - $ref: "#/components/parameters/From"
        - $ref: "#/components/parameters/To"
      responses:
        "200":
          description: Trip collection.
  /trips/{tripId}/route:
    get:
      operationId: getTripRoute
      tags: [Telemetry]
      summary: Get a trip route.
      parameters:
        - name: tripId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Trip route.
  /reports:
    get:
      operationId: listReports
      tags: [Reports]
      summary: List saved reports.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Report collection.
    post:
      operationId: saveReport
      tags: [Reports]
      summary: Save a report definition.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "201":
          description: Report saved.
  /reports/{reportId}/run:
    post:
      operationId: runReport
      tags: [Reports]
      summary: Run a saved report.
      parameters:
        - name: reportId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "202":
          description: Report run accepted.
  /report-runs/{runId}:
    get:
      operationId: getReportRun
      tags: [Reports]
      summary: Get report run status and cached result metadata.
      parameters:
        - name: runId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Report run detail.
  /report-templates:
    get:
      operationId: listReportTemplates
      tags: [Reports]
      summary: List report templates available to the customer.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Report template collection.
    post:
      operationId: createReportTemplate
      tags: [Reports]
      summary: Create a reusable report template.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "201":
          description: Report template created.
  /reports/ai/catalog:
    get:
      operationId: getReportAiCatalog
      tags: [Reports]
      summary: List AI-allowed report datasets, filters, and widget types.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Report AI catalog.
  /reports/ai/preview:
    post:
      operationId: previewReportAiDefinition
      tags: [Reports]
      summary: Validate and preview an AI-proposed report definition.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "200":
          description: Report preview.
  /connectors:
    get:
      operationId: listConnectors
      tags: [Connectors]
      summary: List customer-owned connectors.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Connector collection.
    post:
      operationId: createConnector
      tags: [Connectors]
      summary: Create a connector and return its one-time secret.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [connectorKey, displayName, capabilities]
              properties:
                connectorKey:
                  type: string
                displayName:
                  type: string
                capabilities:
                  type: array
                  items:
                    type: string
      responses:
        "201":
          description: Connector created.
  /connectors/{connectorId}/secret/rotate:
    post:
      operationId: rotateConnectorSecret
      tags: [Connectors]
      summary: Rotate a connector auth secret.
      parameters:
        - name: connectorId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Secret rotated and shown once.
  /connectors/{connectorId}/provisioning-items:
    get:
      operationId: listConnectorProvisioning
      tags: [Connectors]
      summary: Review staged connector provisioning items.
      parameters:
        - name: connectorId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Provisioning queue.
  /connectors/{connectorId}/provisioning-items/{itemId}/apply:
    post:
      operationId: applyConnectorProvisioning
      tags: [Connectors]
      summary: Apply a staged provisioning item.
      parameters:
        - name: connectorId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: itemId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Provisioning item applied.
  /connectors/{connectorId}/provisioning-items/{itemId}/reject:
    post:
      operationId: rejectConnectorProvisioning
      tags: [Connectors]
      summary: Reject a staged provisioning item.
      parameters:
        - name: connectorId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: itemId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
      responses:
        "200":
          description: Provisioning item rejected.
  /driver/trips/active:
    get:
      operationId: getDriverActiveTrip
      tags: [Driver Mobile]
      summary: Restore the authenticated driver's fresh active trip, if one exists.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      responses:
        "200":
          description: Active driver session and vehicle, or nulls when no fresh session exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DriverTripActiveResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /driver/trips/start:
    post:
      operationId: startDriverTrip
      tags: [Driver Mobile]
      summary: Open an active driver-vehicle session after vehicle confirmation.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DriverTripStartRequest"
      responses:
        "201":
          description: Driver vehicle session opened.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DriverTripSessionResponse"
        "409":
          description: Driver or vehicle already has an active open session.
  /driver/trips/stop:
    post:
      operationId: stopDriverTrip
      tags: [Driver Mobile]
      summary: Close the authenticated driver's active driver-vehicle session.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DriverTripStopRequest"
      responses:
        "200":
          description: Driver vehicle session closed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DriverTripSessionResponse"
  /driver/heartbeat:
    post:
      operationId: heartbeatDriverTrip
      tags: [Driver Mobile]
      summary: Refresh app/session heartbeat and optional vehicle attachment state.
      description: >
        Valid vehicleConnectionState values are connected, grace, and disconnected.
        GPS or heartbeat freshness alone does not prove the driver remains attached
        to the vehicle.
      parameters:
        - $ref: "#/components/parameters/CustomerIdHeader"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DriverHeartbeatRequest"
      responses:
        "200":
          description: Driver vehicle session refreshed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DriverTripSessionResponse"
        "404":
          $ref: "#/components/responses/NotFound"
  /ingest/http/raw:
    post:
      operationId: ingestRawTelemetry
      tags: [Ingest]
      security:
        - connectorHmac: []
      summary: Push signed GPS, CAN, or tachograph-shaped raw telemetry.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RawIngest"
      responses:
        "202":
          description: Telemetry accepted for asynchronous processing.
        "401":
          $ref: "#/components/responses/Unauthorized"
  /ingest/http/logs:
    get:
      operationId: getConnectorIngestLogs
      tags: [Ingest]
      security:
        - connectorHmac: []
      summary: Read connector-scoped ingest debug logs.
      description: >
        Returns recent raw ingest receipts, staged provisioning items, and
        validation hints for the authenticated connector only. Sign the path
        /ingest/http/logs without the query string and use an empty raw body.
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        "200":
          description: Connector debug logs.
          content:
            application/json:
              schema:
                type: object
        "401":
          $ref: "#/components/responses/Unauthorized"
  /ingest/http/provisioning/vehicles:
    post:
      operationId: ingestProvisioningVehicles
      tags: [Ingest]
      security:
        - connectorHmac: []
      summary: Stage vehicles from a customer-owned connector.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [vehicles]
              properties:
                vehicles:
                  type: array
                  items:
                    $ref: "#/components/schemas/ProvisionedVehicle"
      responses:
        "202":
          description: Vehicles staged for admin review.
  /ingest/http/provisioning/drivers:
    post:
      operationId: ingestProvisioningDrivers
      tags: [Ingest]
      security:
        - connectorHmac: []
      summary: Stage drivers from a customer-owned connector.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [drivers]
              properties:
                drivers:
                  type: array
                  items:
                    $ref: "#/components/schemas/ProvisionedDriver"
      responses:
        "202":
          description: Drivers staged for admin review.
  /ingest/http/tachograph/download-result:
    post:
      operationId: ingestTachographDownloadResult
      tags: [Ingest]
      security:
        - connectorHmac: []
      summary: Push a tachograph remote-download artifact result.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TachographDownloadResult"
      responses:
        "202":
          description: Download result accepted.
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    connectorHmac:
      type: apiKey
      in: header
      name: X-Ingest-Signature
      description: >
        HMAC signature with X-Connector-Key, X-Ingest-Timestamp, and
        X-Ingest-Nonce. The developer portal connector tool can generate these
        headers.
  parameters:
    CustomerIdHeader:
      name: X-Customer-Id
      in: header
      required: false
      schema:
        type: string
        format: uuid
      description: Required for customer-scoped routes.
    ResellerIdHeader:
      name: X-Reseller-Id
      in: header
      required: false
      schema:
        type: string
      description: Required for reseller-scoped admin and billing routes.
    CustomerPath:
      name: customerId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    UserPath:
      name: userId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    VehiclePath:
      name: vehicleId
      in: path
      required: true
      schema:
        type: string
        format: uuid
    VehicleIdQuery:
      name: vehicle_id
      in: query
      required: false
      schema:
        type: string
        format: uuid
    From:
      name: from
      in: query
      required: false
      schema:
        type: string
        format: date-time
    To:
      name: to
      in: query
      required: false
      schema:
        type: string
        format: date-time
    Page:
      name: page
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        default: 1
    PageSize:
      name: page_size
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 500
        default: 50
  responses:
    Unauthorized:
      description: Authentication failed.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Forbidden:
      description: Permission or tenant access denied.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
  schemas:
    AuthSessionBundle:
      type: object
      properties:
        user:
          type: object
        memberships:
          type: array
          items:
            type: object
        tokens:
          type: object
          properties:
            accessToken:
              type: string
            refreshToken:
              type: string
            tokenType:
              type: string
            expiresInSeconds:
              type: integer
    MeResponse:
      type: object
      properties:
        user:
          type: object
        memberships:
          type: array
          items:
            type: object
        adminWebEligible:
          type: boolean
        linkedResellerAccounts:
          type: array
          items:
            type: object
        activeResellerAccountId:
          type: string
          nullable: true
    CollectionResponse:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
        meta:
          type: object
    CustomerWrite:
      type: object
      properties:
        name:
          type: string
        status:
          type: string
        parentCustomerId:
          type: string
          format: uuid
        resellerAccountId:
          type: string
    UserWrite:
      type: object
      properties:
        email:
          type: string
          format: email
        password:
          type: string
        displayName:
          type: string
        status:
          type: string
        tachographCardNumber:
          type: string
    VehicleWrite:
      type: object
      properties:
        displayName:
          type: string
        vin:
          type: string
        plateNumber:
          type: string
        category:
          type: string
        status:
          type: string
    DriverVehicleSession:
      type: object
      properties:
        sessionId:
          type: string
          format: uuid
        customerId:
          type: string
          format: uuid
        vehicleId:
          type: string
          format: uuid
        driverUserId:
          type: string
          format: uuid
        status:
          type: string
          enum: [active, stopped]
        startedAt:
          type: string
          format: date-time
        lastHeartbeatAt:
          type: string
          format: date-time
          nullable: true
        vehicleConnectionState:
          type: string
          enum: [connected, grace, disconnected]
        vehicleConnectionLastSeenAt:
          type: string
          format: date-time
          nullable: true
        endedAt:
          type: string
          format: date-time
          nullable: true
        endedReason:
          type: string
          nullable: true
        metadata:
          type: object
    DriverTripSessionResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            session:
              $ref: "#/components/schemas/DriverVehicleSession"
    DriverTripActiveResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            session:
              anyOf:
                - $ref: "#/components/schemas/DriverVehicleSession"
                - type: "null"
            vehicle:
              anyOf:
                - type: object
                - type: "null"
    DriverTripStartRequest:
      type: object
      required: [vehicleId]
      properties:
        vehicleId:
          type: string
          format: uuid
        startedAt:
          type: string
          format: date-time
        transfer:
          type: boolean
        transferReason:
          type: string
        metadata:
          type: object
    DriverTripStopRequest:
      type: object
      properties:
        sessionId:
          type: string
          format: uuid
        endedAt:
          type: string
          format: date-time
        reason:
          type: string
        metadata:
          type: object
    DriverHeartbeatRequest:
      type: object
      required: [sessionId]
      properties:
        sessionId:
          type: string
          format: uuid
        heartbeatAt:
          type: string
          format: date-time
        vehicleId:
          type: string
          format: uuid
        vehicleConnectionState:
          type: string
          enum: [connected, grace, disconnected]
        vehicleConnectionLastSeenAt:
          type: string
          format: date-time
        metadata:
          type: object
    RawIngest:
      type: object
      required: [connectorKey, endpoint, customerId, eventTs, payloadJson]
      properties:
        connectorKey:
          type: string
        endpoint:
          type: string
        customerId:
          type: string
          format: uuid
        vehicleId:
          type: string
          format: uuid
        deviceId:
          type: string
          format: uuid
        externalVehicleId:
          type: string
        externalDriverId:
          type: string
        eventTs:
          type: string
          format: date-time
        payloadJson:
          type: object
    ProvisionedVehicle:
      type: object
      required: [externalId]
      properties:
        externalId:
          type: string
        vin:
          type: string
        plateNumber:
          type: string
        manufacturer:
          type: string
        model:
          type: string
        timezone:
          type: string
    ProvisionedDriver:
      type: object
      required: [externalId, email, displayName]
      properties:
        externalId:
          type: string
        email:
          type: string
          format: email
        displayName:
          type: string
        tachographCardNumber:
          type: string
        temporaryPassword:
          type: string
        phone:
          type: string
    TachographDownloadResult:
      type: object
      required: [connectorKey, resultStatus]
      properties:
        connectorKey:
          type: string
        connectorId:
          type: string
          format: uuid
        customerId:
          type: string
          format: uuid
        deviceId:
          type: string
          format: uuid
        vehicleId:
          type: string
          format: uuid
        driverUserId:
          type: string
          format: uuid
        sessionId:
          type: string
          format: uuid
        downloadedAt:
          type: string
          format: date-time
        resultStatus:
          type: string
          enum: [completed, unsupported, failed]
        artifact:
          type: object
          properties:
            artifactKey:
              type: string
            fileName:
              type: string
            contentType:
              type: string
            artifactJson:
              type: object
            artifactText:
              type: string
            artifactBase64:
              type: string
            metadata:
              type: object
        metadata:
          type: object
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: array
              items: {}
