openapi: 3.0.0
info:
  title: INVERS CloudBoxx Bluetooth Token Management API
  description: |
    The CloudBoxx Bluetooth Token Management API is intended for INVERS customers who need programmatic access to integrate their applications with the INVERS platform.

    The base URL for all endpoints described here is `https://api.invers.com`. Learn more in our [Integration Guide](https://developers.invers.com/integration-guide/) and [common API rules](https://developers.invers.com/integration-guide/api-basics/).

    The CloudBoxx Bluetooth Token Management API provides resources to create and manage Bluetooth tokens for your vehicles with an installed CloudBoxx.
    These tokens can be used to communicate with the CloudBoxx inside a vehicle directly via Bluetooth.

    ## Creating new tokens
    New CloudBoxx Bluetooth tokens are generated for a vehicle by specifying its `vehicle_id` in the request body.
    You don't need to specify the ID of the telematics unit, i.e. the QNR of the CloudBoxx, when creating a new token.

    Every token has a validity interval during which it can be used to authenticate against the associated CloudBoxx.
    This interval is specified by the request parameters `valid_from` and `valid_until`.
    A token is considered expired if `valid_until` is in the past.
    `valid_until` may extend a maximum of 40 days into the future.
    An expired token can no longer authenticate successfully against a CloudBoxx.

    A token can grant different levels of control over a vehicle dependent on the `access_level` request parameter.
    Setting this parameter to `OPEN_CLOSE` only allows unlocking and locking the central lock of the vehicle
    whereas `OPEN_CLOSE_DRIVE` also allows to enable and disable driving.

    ## Fleet sharing
    When sharing vehicles with an installed CloudBoxx the sharing partner can create new tokens for the vehicles.
    However the amount of unexpired tokens per vehicle is limited to 10 in that case.
    Additionally no tokens can be created by the partner that last longer than the sharing interval for the vehicle
    or that have an indefinite or excessive `valid_until` timestamp.

    All tokens created by the owner stay valid during the sharing period.
    If fleet sharing is ended prematurely all tokens created by the partner get suspended.

    ## Suspending tokens
    CloudBoxx Bluetooth tokens can be suspended,
    meaning that they can no longer be used to authenticate successfully against the CloudBoxx
    despite not being expired, i.e. still being valid according to the validity interval.
    This can be used to immediately withdraw access to the CloudBoxx using this token.

    Suspending and unsuspending tokens requires direct communication with the CloudBoxx.
    So in case the CloudBoxx is offline or doesn't respond im time,
    you can expect a problem response with status code 504.

    Note that for each CloudBoxx, a maximum of 50 suspensions can be active at the same time,
    i.e. if you already have 50 suspended unexpired tokens and try to suspend another
    you will receive a problem response with status code 409.
    This limit only considers tokens that are not expired
    as an expired token can no longer be used for authentication anyways
    and doesn't have to be blacklisted explicitly by the CloudBoxx.
  contact:
    name: INVERS GmbH
    url: https://developers.invers.com/
  version: 1.1.1
  x-api-id: 32c03ace-fd74-4af1-ba5b-8c65df99e82f
  x-audience: external-public
servers:
  - url: https://api.invers.com
    description: INVERS OneAPI
tags:
  - name: CloudBoxx Bluetooth tokens
    description: These resources can be used to create and manage CloudBoxx Bluetooth tokens.
paths:
  /telematics-brands/cloudboxx/bluetooth-tokens:
    post:
      operationId: postBluetoothToken
      tags:
        - CloudBoxx Bluetooth tokens
      security:
        - OAuth2:
            - VEHICLE_OFFLINE_ACCESS
      x-invers-permission: vehicle-offline-access
      summary: Create a new CloudBoxx Bluetooth token
      description: |
        Creates a new token that can be used to communicate with the CloudBoxx
        installed in the vehicle specified by the `vehicle_id` in the request body
        directly via Bluetooth.

        Note that the actual `token` itself and the `session_key` in the response can not be retrieved again later,
        so it is the task of the API user to store them.
      requestBody:
        $ref: '#/components/requestBodies/CloudBoxxBluetoothTokenCreateRequest'
      responses:
        '201':
          description: The created token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CloudBoxxBluetoothToken'
        '400':
          description: |
            The request is invalid.
            See examples for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                The vehicle with the specified ID does not exist:
                  value:
                    type: /problems/referenced-resource-not-found
                    type_documentation: https://developers.invers.com/problems/referenced-resource-not-found
                    title: A referenced resource cannot be found.
                    status: 400
                    detail: The vehicle with ID 'MT3T3' does not exist.
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
                The specified vehicle has no CloudBoxx installed:
                  value:
                    type: /problems/referenced-resource-not-found
                    type_documentation: https://developers.invers.com/problems/referenced-resource-not-found
                    title: A referenced resource cannot be found.
                    status: 400
                    detail: The vehicle with ID 'MT3T3' has no CloudBoxx installed.
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
                A required property was not specified in the request:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: The property 'valid_until' must not be empty.
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
                The specified validity interval is invalid:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: '''valid_until'' must be in the future.'
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
                The specified validity interval exceeds the maximum duration:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: '''valid_until'' must not be more than 40 days in the future.'
                The specified validity interval exceeds sharing:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: '''valid_until'' must be before the sharing of the vehicle ends.'
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
        '409':
          description: |
            The request would exceed a resource limit.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: /problems/quota-exceeded
                type_documentation: https://developers.invers.com/problems/quota-exceeded
                title: A resource limit was exceeded.
                status: 409
                detail: You cannot have more than 10 unexpired tokens for a shared vehicle.
                flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
    get:
      operationId: getBluetoothToken
      tags:
        - CloudBoxx Bluetooth tokens
      security:
        - OAuth2:
            - VEHICLE_OFFLINE_ACCESS
      x-invers-permission: vehicle-offline-access
      summary: Get the metadata of multiple CloudBoxx Bluetooth tokens
      description: |
        Gets the metadata of multiple CloudBoxx Bluetooth tokens.
        If no tokens exist, an empty list will be returned.
      parameters:
        - name: vehicle_id
          in: query
          description: Narrows down the list of tokens to ones associated with the vehicle with the given `vehicle_id`.
          required: false
          schema:
            type: string
            maxLength: 12
            example: JQ7RP
        - name: telematics_unit_id
          in: query
          description: Narrows down the list of tokens to ones associated with the CloudBoxx with the given `telematics_unit_id`.
          required: false
          schema:
            type: string
            maxLength: 40
            example: 38429DA427AB7C25
        - name: include_suspended
          in: query
          description: Specifies whether to include suspended tokens in the resulting list.
          required: false
          schema:
            type: boolean
            default: true
            example: false
        - name: include_expired
          in: query
          description: Specifies whether to include expired tokens in the resulting list.
          required: false
          schema:
            type: boolean
            default: true
            example: false
        - name: limit
          in: query
          description: Number of items to return at most
          required: false
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 1000
            default: 100
            example: 10
        - name: cursor
          in: query
          description: |
            The cursor object used to navigate through the results.
            When using a cursor, no additional query parameters should be provided.
          required: false
          schema:
            type: string
            maxLength: 200
            example: eyJ2IjpbIjIwMjAtMTEtMTZUMDk6NTc6MjUuNDUwMDAwMFoiLCJOWUNOVSJdLCJkIjpmYWxzZSwicSI6eyJsIjozfX0=
      responses:
        '200':
          description: A list of CloudBoxx Bluetooth tokens
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CloudBoxxBluetoothTokenMetadataList'
        '400':
          description: |
            The request was invalid.
            See examples for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                Invalid query parameters:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: Cannot specify query parameters when 'cursor' is used. Do not provide any other search-related query parameters when using the cursor.
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
                Invalid cursor:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: The provided 'cursor' is invalid.
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
                Invalid value for query parameter:
                  value:
                    type: /problems/validation-error
                    type_documentation: https://developers.invers.com/problems/validation-error
                    title: Validation Error
                    status: 400
                    detail: The provided 'vehicle_id' is invalid.
                    flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
  /telematics-brands/cloudboxx/bluetooth-tokens/{id}:
    parameters:
      - $ref: '#/components/parameters/TokenIdParameter'
    get:
      operationId: getBluetoothTokenById
      tags:
        - CloudBoxx Bluetooth tokens
      security:
        - OAuth2:
            - VEHICLE_OFFLINE_ACCESS
      x-invers-permission: vehicle-offline-access
      summary: Get the metadata of a CloudBoxx Bluetooth token
      description: |
        Gets the metadata of a CloudBoxx Bluetooth token by its ID.
      responses:
        '200':
          description: The metadata of the CloudBoxx Bluetooth token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CloudBoxxBluetoothTokenMetadata'
        '404':
          description: |
            The specified token was not found.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                The specified token does not exist:
                  $ref: '#/components/examples/TokenDoesNotExist'
  /telematics-brands/cloudboxx/bluetooth-tokens/{id}/suspension:
    parameters:
      - $ref: '#/components/parameters/TokenIdParameter'
    put:
      operationId: suspendBluetoothToken
      tags:
        - CloudBoxx Bluetooth tokens
      security:
        - OAuth2:
            - VEHICLE_OFFLINE_ACCESS
      x-invers-permission: vehicle-offline-access
      summary: Suspend a CloudBoxx Bluetooth token
      description: |
        Suspends a CloudBoxx Bluetooth token specified by its ID.
        A suspended token can no longer be used to authenticate against a CloudBoxx.

        For each CloudBoxx, a maximum of 50 suspensions can be active at the same time,
        i.e. if you already have 50 suspended unexpired tokens and try to suspend another
        you will receive a problem response with status code **409**.
        As mentioned before, this limit only considers tokens that are not already expired.

        Communicating with the CloudBoxx is required in order to suspend a token.
        If the CloudBoxx is offline or does not respond in time you will receive a problem response with status code **504**.
        Our background service will attempt to retransmit the suspension when the CloudBoxx is available again until the token expires.
        You can check the current transmission status at the `suspension.is_transmitted` property of the token metadata. 
      responses:
        '204':
          description: The CloudBoxx Bluetooth token has been suspended.
        '404':
          description: |
            The specified token was not found.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                The specified token does not exist:
                  $ref: '#/components/examples/TokenDoesNotExist'
        '409':
          description: |
            The request would exceed a resource limit.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: /problems/quota-exceeded
                type_documentation: https://developers.invers.com/problems/quota-exceeded
                title: A resource limit was exceeded.
                status: 409
                detail: You cannot have more than 50 suspended unexpired tokens for a CloudBoxx at the same time.
                flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
        '504':
          description: |
            The CloudBoxx is offline or did not respond in time.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: /problems/vehicle/no-connection
                type_documentation: https://developers.invers.com/problems/vehicle/no-connection
                title: No connection to vehicle
                status: 504
                detail: The CloudBoxx is offline or did not respond in time.
                flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
    delete:
      operationId: unsuspendBluetoothToken
      tags:
        - CloudBoxx Bluetooth tokens
      security:
        - OAuth2:
            - VEHICLE_OFFLINE_ACCESS
      x-invers-permission: vehicle-offline-access
      summary: Unsuspend a CloudBoxx Bluetooth token
      description: |
        Removes the suspension for a CloudBoxx Bluetooth token specified by its ID,
        if it is currently suspended.

        Communicating with the CloudBoxx is required in order to unsuspend a token.
        If the CloudBoxx is offline or does not respond in time you will receive a problem response with status code **504**.
        Our background service will attempt to retransmit the suspension when the CloudBoxx is available again until the token expires.
        You can check the current transmission status at the `suspension.is_transmitted` property of the token metadata. 
      responses:
        '204':
          description: |
            The suspension for the CloudBoxx Bluetooth token has been removed,
            or the token was not suspended at all.
        '404':
          description: |
            The specified token was not found.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                The specified token does not exist:
                  $ref: '#/components/examples/TokenDoesNotExist'
        '504':
          description: |
            The CloudBoxx is offline or did not respond in time.
            See example for more details.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: /problems/vehicle/no-connection
                type_documentation: https://developers.invers.com/problems/vehicle/no-connection
                title: No connection to vehicle
                status: 504
                detail: The CloudBoxx is offline or did not respond in time.
                flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
components:
  requestBodies:
    CloudBoxxBluetoothTokenCreateRequest:
      description: Metadata for the CloudBoxx Bluetooth token to be created.
      required: true
      content:
        application/json:
          schema:
            required:
              - vehicle_id
              - access_level
              - valid_from
              - valid_until
            properties:
              vehicle_id:
                $ref: '#/components/schemas/VehicleIdProperty'
              access_level:
                description: |
                  Controls the level of access the token grants.
                  `OPEN_CLOSE` only allows unlocking and locking the central lock
                  whereas `OPEN_CLOSE_DRIVE` also allows to enable and disable driving.
                type: string
                maxLength: 64
                x-extensible-enum:
                  - OPEN_CLOSE_DRIVE
                  - OPEN_CLOSE
                example: OPEN_CLOSE
              valid_from:
                $ref: '#/components/schemas/ValidFromProperty'
              valid_until:
                description: |
                  UTC time until which the token can be used to communicate with the CloudBoxx.

                  Must not be more than 40 days in the future.
                type: object
                allOf:
                  - $ref: '#/components/schemas/ValidUntilProperty'
  parameters:
    TokenIdParameter:
      name: id
      in: path
      description: UUID of the token
      required: true
      schema:
        type: string
        format: UUID
        example: 769e50c1-b129-47f1-8244-4ca86e637cf6
        maxLength: 36
  schemas:
    VehicleIdProperty:
      description: Unique ID of the vehicle
      type: string
      maxLength: 12
      example: JQ7RP
    QnrProperty:
      description: The QNR of the CloudBoxx that the token is associated with.
      type: string
      maxLength: 40
      example: 38429DA427AB7C25
    TokenIdProperty:
      description: UUID of the Bluetooth token to be used for getting metadata/invalidation and for reference in events
      type: string
      format: UUID
      maxLength: 36
      example: 769e50c1-b129-47f1-8244-4ca86e637cf6
    ValidFromProperty:
      description: UTC time from which the token can be used to communicate with the CloudBoxx
      type: string
      format: date-time
      example: '2023-02-14T14:13:01.701Z'
    ValidUntilProperty:
      description: UTC time until which the token can be used to communicate with the CloudBoxx
      type: string
      format: date-time
      example: '2023-02-28T14:29:13.135Z'
    AccessLevelProperty:
      description: |
        Controls the level of access the token grants.
        - `OPEN_CLOSE` only allows unlocking and locking the central lock
        - `OPEN_CLOSE_DRIVE` also allows to enable and disable driving
        - `CONFIGURE` allows pairing Keyfob and RFID tags
      type: string
      maxLength: 64
      x-extensible-enum:
        - OPEN_CLOSE_DRIVE
        - OPEN_CLOSE
        - CONFIGURE
      example: OPEN_CLOSE
    TokenCreatedAtProperty:
      description: UTC time of when the token has been created.
      type: string
      format: date-time
      example: '2023-02-14T14:13:03.178Z'
    CloudBoxxBluetoothToken:
      description: CloudBoxx Bluetooth token
      type: object
      required:
        - id
        - token
        - session_key
        - valid_from
        - valid_until
        - access_level
        - vehicle_id
        - telematics_unit_id
        - created_at
      properties:
        id:
          $ref: '#/components/schemas/TokenIdProperty'
        token:
          description: Actual token to be used to authenticate against the CloudBoxx
          type: string
          format: base64
          maxLength: 200
          example: nmleqT+DRBvev/zQqT4TCxr7MN5KjIITVK0iA7SihSGsV8S9lWPQSQFm3C0I3uBaBYeGfZitKkrSRas3+Q+UQYy3pmbYped3Vud576+ax9yoqpp0duL+3iVB+2vIWXQLXg5vtg==
        session_key:
          description: Session key to be used for communication with the CloudBoxx
          type: string
          format: base64
          maxLength: 24
          example: p/UqTuw7Wvm9iN53JP+hng==
        valid_from:
          $ref: '#/components/schemas/ValidFromProperty'
        valid_until:
          $ref: '#/components/schemas/ValidUntilProperty'
        access_level:
          $ref: '#/components/schemas/AccessLevelProperty'
        vehicle_id:
          $ref: '#/components/schemas/VehicleIdProperty'
        telematics_unit_id:
          $ref: '#/components/schemas/QnrProperty'
        created_at:
          $ref: '#/components/schemas/TokenCreatedAtProperty'
    CloudBoxxBluetoothTokenMetadata:
      description: CloudBoxx Bluetooth token metadata
      type: object
      required:
        - id
        - valid_from
        - valid_until
        - access_level
        - vehicle_id
        - telematics_unit_id
        - created_at
      properties:
        id:
          $ref: '#/components/schemas/TokenIdProperty'
        created_at:
          $ref: '#/components/schemas/TokenCreatedAtProperty'
        vehicle_id:
          $ref: '#/components/schemas/VehicleIdProperty'
        telematics_unit_id:
          $ref: '#/components/schemas/QnrProperty'
        valid_from:
          $ref: '#/components/schemas/ValidFromProperty'
        valid_until:
          $ref: '#/components/schemas/ValidUntilProperty'
        access_level:
          $ref: '#/components/schemas/AccessLevelProperty'
        suspension:
          description: The suspension details for the token
          type: object
          required:
            - created_at
            - is_transmitted
            - is_suspended
          properties:
            created_at:
              description: |
                UTC time of when the suspension has been created.
                If a token gets suspended multiple times, this property remains the same,
                i.e. it still reflects the first point in time that the token was suspended.
              type: string
              format: date-time
              example: '2023-02-16T11:57:11.633Z'
            is_transmitted:
              description: |
                Indicates whether the token suspension transmission was successful.
                The transmission requires a connection to the CloudBoxx and may fail if the device has a poor connection.
                The transmission is retried once per hour.
              type: boolean
              example: true
            is_suspended:
              description: |
                Indicates the suspension status of the token
                * true and `is_transmitted=true` - the token is suspended
                * true and `is_transmitted=false` - the token must be suspended, but the transmission failed so far
                * false and `is_transmitted=true` - the token is not suspended
                * false and `is_transmitted=false` - the token should not be suspended, but the (unsuspend) transmission failed so far
              type: boolean
              example: true
    CloudBoxxBluetoothTokenMetadataList:
      required:
        - items
        - cursors
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/CloudBoxxBluetoothTokenMetadata'
        cursors:
          type: object
          description: |
            Contains the relevant cursors for the returned page.
            `prev` and `next` are omitted if they are not applicable.

            Usually the `next` cursor is used repeatedly to iterate over the result list.
          required:
            - self
          properties:
            self:
              type: string
              description: |
                Use as `cursor` query parameter in order to retrieve the same batch of results as currently returned
                (according to the limit parameter previously provided).
              maxLength: 200
              example: eyJ2IjpbIjIwMjAtMTEtMTZUMDk6NTc6MjUuNDUwMDAwMFoiLCJOWUNOVSJdLCJkIjpmYWxzZSwicSI6eyJsIjozfX0=
            prev:
              type: string
              description: |
                Use as `cursor` query parameter in order to retrieve the previous batch of results
                (according to the limit parameter previously provided).
              maxLength: 200
              example: eyJ2IjpbIjIwMjAtMTEtMTZUMDk6NTc6MjUuNTYxMDAwMFoiLCJOVEY1VCJdLCJkIjp0cnVlLCJxIjp7ImwiOjN9fQ==
            next:
              type: string
              description: |
                Use as `cursor` query parameter in order to retrieve the next batch of results
                (according to the limit parameter previously provided).
              maxLength: 200
              example: eyJ2IjpbIjIwMjAtMTEtMTZUMDk6NTc6MjUuNzY2MDAwMFoiLCJaOTVSUyJdLCJkIjpmYWxzZSwicSI6eyJsIjozfX0=
    Problem:
      type: object
      required:
        - type
        - title
        - status
        - detail
      properties:
        type:
          type: string
          format: uri-reference
          description: |
            A relative URI reference that uniquely identifies the problem type only in the context of the provided API. Opposed to the specification in RFC-7807, it is neither recommended to be dereferencable and point to a human-readable documentation nor globally unique for the problem type.
          default: about:blank
          example: /problem/connection-error
        type_documentation:
          type: string
          format: url
          description: |
            An URL that points to a human-readable documentation of the problem type. Some explanations of the problem type together with possible solutions can be found there.  Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized.
          example: https://developers.invers.com/problems/invalid-credentials/
        title:
          type: string
          description: |
            A short summary of the problem type. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized.
          example: Service Unavailable
        status:
          type: integer
          format: int32
          description: |
            The HTTP status code generated by the origin server for this occurrence of the problem.
          minimum: 100
          maximum: 600
          exclusiveMaximum: true
          example: 503
        detail:
          type: string
          description: |
            A human readable explanation specific to this occurrence of the problem that is helpful to locate the problem and give advice on how to proceed. Written in English and readable for engineers, usually not suited for non technical stakeholders and not localized.
          example: Connection to database timed out
        flow_id:
          type: string
          description: |
            The id of the flow that caused this error.  For more information visit [https://developers.invers.com/integration-guide/api-basics/#flow-id](https://developers.invers.com/integration-guide/api-basics/#flow-id).
  examples:
    TokenDoesNotExist:
      summary: The token does not exist
      value:
        type: /problems/resource-not-found
        type_documentation: https://developers.invers.com/problems/resource-not-found/
        title: The resource cannot be found.
        status: 404
        detail: The token with ID 'd495b1ba-e574-4e8d-a73f-96e7a6b382c9' cannot be found.
        flow_id: 5e77e3e3-48ab-4955-8ab3-1c62339096ab
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: /auth/oauth/token
          scopes:
            VEHICLE_OFFLINE_ACCESS: Send commands to vehicle (using Bluetooth)
        authorizationCode:
          authorizationUrl: /auth/oauth/authorize
          tokenUrl: /auth/oauth/token
          scopes:
            VEHICLE_OFFLINE_ACCESS: Send commands to vehicle (using Bluetooth)
