openapi: 3.0.0
info:
  version: 2.0.1
  title: Shared Bundle API
  x-audience: external-public
  description: |
  
    #### Copyright

    © Aeris Communications, Inc. 2026. All rights reserved. No part of this document may be reproduced in any form without the written permission of the copyright owner.

    #### Disclaimer

    The contents of this document are subject to revision without notice due to continued progress in methodology, design and manufacturing.
    Aeris shall have no liability for any error or damage of any kind resulting from the use of this document.

    # Introduction

    This document describes the IoT Accelerator Shared Bundle API that provides resources
    to retrieve information about an organizations usage and limits of shared bundles.
    The Shared Bundle API is based on the Representational State Transfer (REST) interface.
    From this point on, the Shared Bundle API is referred to as API in this document.
    
    ## Related Information
    The definition and explanation of acronyms and terminology and typographic conventions can be found in the following documents:

    — DCP Glossary of Terms and Acronyms

    — Typographic Conventions

    — Price Plan User Guide for definition and types of shared bundles

    ## Shared Bundle
    A 'shared bundle' is in this context defined as a volume of connectivity service (e.g. traffic volume) that many subscriptions (e.g. SIMs in IoT devices) can use in each billing period without incurring usage-based connectivity charges.
    
    The traffic volume is shared among all subscriptions that belong to the same price profile or organisation, depending on the shared bundle configuration.
    
    After the shared bundle is depleted for the given service, usage-based charges apply for all additional traffic.

    ## User Stories

    - *As a financial controller in an organization with cellular IoT connected devices,
    I need to be able to retrieve and monitor the remianing traffic volume and compare with the monthly service shared bundle limits,
    so I can predict monthly traffic and costs.*

    - *As an operations engineer in an organization with cellular IoT connected devices,
    I need to daily monitor the remaining traffic volume, 
    so I can take action before shared bundle limits are reached when needed.*

    ## Description
    The service provide an organisation with visibility of used and remaining traffic volumes for shared bundles.
    
    Supported shared bundle types are:
    - Fixed shared bundle - a fixed amount of granted traffic.
    - SIM dependent shared bundles - each SIM that is included in the shared bundle contributes to the granted traffic volume.

    **Capabilities:**
    - Shared bundle information is made accessible for an organisation for the previous and current billing period.
    - For the current billing period, shared bundle information is provided after the first five (5) days has passed.
    - Billable volumes are presented per shared bundle for bearer services as configured in price plans and price profiles.
    - Values presented per shared bundle include granted and remaining traffic volume.
    - Shared bundle information is updated approximate once per hour, but the update frequency may be longer or shorter. A time stamp is provided to reflect the time of capture.
    
    Note: A billing period is usually a calendar Month.
    
    # General API Guidelines

    ## Compatibility

    API audience must be prepared for compatible API extensions:

    - Be tolerant with unknown fields in the payload (see also Fowler’s "TolerantReader" post), i.e. ignore new fields but do not eliminate them from payload if needed for subsequent PUT requests.
    - Be prepared that "x-extensible-enum" return parameter may deliver new values. Either be agnostic or provide default behavior for unknown values.
    - Be prepared to handle HTTP status codes not explicitly specified in endpoint definitions.
    - Follow the redirect when the server returns HTTP status 301 Moved Permanently.

    ## Security

    This section describes the security measures in the API. Security measures include authentication, authorization, and encryption.

    ### Authentication and Authorization

    The API uses OAuth2 and OpenID Connect (OIDC) for authentication and authorization.

    All API endpoints require authentication, which is performed by passing a token in the Authorization header in each request, preceded by the word Bearer and a space. See the following example:
    ```
    curl -i -X GET "http://<baseURL>/iot/api/shared-bundles" -H "Content-Type: application/json" -H "Authorization: Bearer <TOKEN_GOES_HERE>"
    ```
    To fetch the token using e.g. curl, submit the following:
    ```
    curl -X POST "https://<baseURL>/iot/api/auth/token" -H "Accept: application/vnd.dcp-v1+json" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&client_id=<client_id>&username=<username>&password=<password>"
    ```
    ### Encryption

    All API requests are encrypted using the HTTPS protocol to grant secure data transfer.

    ## Deprecation

    API deprecation will be reflected in the OpenAPI definition. If a method on a path, a whole path or even a whole API endpoint (multiple paths) should be deprecated, they will be marked as deprecated.
    During deprecation phase, a Warning header (see RFC 7234 - Warning header) field will be added in the response. The warn-code will be 299 and the warn-text will inform about what is deprecated and when it will be completely removed.

    API audience should not start using a deprecated API.

    API audience is encouraged to monitor for Warning header.
    
servers:
- url: https://iot-api.aeris.com/iot/api
  description: API server

tags:
- name: Actions 

paths:
  /shared-bundles:
    parameters:
      - $ref: '#/components/parameters/qParam'
      - $ref: '#/components/parameters/sortParam'
      - $ref: '#/components/parameters/cycleParam'
      - $ref: '#/components/parameters/limitParam'
      - $ref: '#/components/parameters/cursorParam'
    get:
      summary: List shared bundles
      description: |
       Return a list of all shared bundles, or an empty list if no shared bundle information is available.
      operationId: AllSharedBundleConsumptionGet
      tags:
        - Actions
      responses:
        '200':
          description: Response to a successful GET.
          allOf:
            - $ref: '#/components/schemas/RateLimitedResponse'
          content:
            application/json:
              schema:
                type: object
                properties:
                  shared_bundles:
                    type: array
                    items:
                      $ref: '#/components/schemas/SharedBundleSummaryResponse'
                  next:
                    description: Link to the next page of results. If not included, there are no more results.
                    type: string
                    format: uri
                    example: 'https://iot-api.aeris.com/iot/api/shared-bundles?cursor=DFVSDB3434%DFB%EYY445'
              example:
                shared_bundles:
                  - id: 48e0b7de2c504ab4ac6b98176cfacbba
                    service_type: DATA
                    granted: 29000000000
                    remaining: 3468702000
                    cycle_started_at: '2020-10-01T00:00:00.000Z'
                    cycle_ended_at: '2020-11-01T00:00:00.000Z'
                    organization_id: '0.5.2.3'
                  - id: 12cc0525eaec4f76881b7af2b3a55cbc
                    service_type: SMS
                    granted: 4314
                    remaining: 2797
                    cycle_started_at: '2020-10-01T00:00:00.000Z'
                    cycle_ended_at: '2020-11-01T00:00:00.000Z'
                    organization_id: '0.5.2.3'
                  - id: 35285cc0561d4481abb07e1354d629ed
                    service_type: SMS
                    granted: 20
                    remaining: 20
                    cycle_started_at: '2020-10-01T00:00:00.000Z'
                    cycle_ended_at: '2020-11-01T00:00:00.000Z'
                    organization_id: '0.5.2.3'
                  - id: 1efc17de2f274467be49e940b4911839
                    service_type: DATA
                    granted: 2097152000
                    remaining: 1971038208
                    cycle_started_at: '2020-10-01T00:00:00.000Z'
                    cycle_ended_at: '2020-11-01T00:00:00.000Z'
                    organization_id: '0.5.2.3'
                  - id: 873b5661f85b453290b4585f7eb8812e
                    service_type: VOICE
                    granted: 6000
                    remaining: 6000
                    cycle_started_at: '2020-10-01T00:00:00.000Z'
                    cycle_ended_at: '2020-11-01T00:00:00.000Z'
                    organization_id: '0.5.2.3'
                next: 'https://iot-api.aeris.com/iot/api/shared-bundles?cursor=DFVSDB3434%DFB%EYY445'
        default:
          description: error occurred - see status code and problem object for more information.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
      security:
        - OAuth2:
            - 'org-mgt.shared-bundle-consumption.read'
  /shared-bundles/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: |
          The Shared Bundle Identifier.
        schema:
          type: string
    get:
      summary: Shared bundle details.
      description: |
        Detailed information of a specific shared bundle.
      operationId: SingleSharedBundleConsumptionGet
      tags:
        - Actions
      responses:
        '200':
          description: Response to a successful GET, also used for a POST if it does not result in a creation.
          allOf:
            - $ref: '#/components/schemas/RateLimitedResponse'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SharedBundleDetailsResponse'
              example:
                id: 48e0b7de2c504ab4ac6b98176cfacbba
                service_type: DATA
                level: PRICE_PROFILE
                price_profile: PP000000001
                type: SIM_DEPENDENT
                granted: 29000000000
                remaining: 3468702000
                updated_at: '2020-10-21T16:51:33.305Z'
                cycle_started_at: '2020-10-01T00:00:00.000Z'
                cycle_ended_at: '2020-11-01T00:00:00.000Z'
                organization_id: "3.88.176.837"
        default:
          description: error occurred - see status code and problem object for more information.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
      security:
        - OAuth2:
            - 'org-mgt.shared-bundle-consumption.read'
components:
  parameters:
    sortParam:
      in: query
      name: sort
      schema:
        type: string
        x-extensible-enum:
          - remaining:asc
          - remaining:desc
          - granted:asc
          - granted:desc
        default: remaining:asc
      description: |
        Parameter containing sort field and sort mode. First part selects field to sort on, the second part the order.

        _Available values:_

        - remaining:asc
        - remaining:desc
        - granted:asc
        - granted:desc
    limitParam:
      in: query
      name: limit
      schema:
        type: integer
        default: 100
      description: |
        Specifies the maximum number of results to be returned. Allowed interval is 1-1000.
    cursorParam:
      in: query
      name: cursor
      schema:
        type: string
      example: 'DFVSDB3434%DFB%EYY445'
      description: |
        Parameter used for pagination. This field is automatically populated in the response field "next" if there are more results in the system than delivered in the response.
    qParam:
      in: query
      name: q
      schema:
        type: string
        example: service_type==sms;organization_id==0.5.2.3
      description: |

        RSQL query string parameter. Selects shared bundles which are filtered by a RSQL compliant query string.

        _Available logical operators:_

        - Logical AND : ; or "and" is supported
        - Logical OR : , or "or" is supported

        'organization_id' can be used to filter out a single Organization. Example '0.5.2.3' \
        'service_type' can be used to filter out bundles by service type. Example 'sms'\
        'granted' can be used to filter out bundles by granted amount.\
        'remaining' can be used to filter out bundles by remaining amount.

        Comparison operators are in FIQL notation.

        _Available comparison operators:_

        - Equal to : ==
        - Not equal to : !=
        - Less than : =lt= or <
        - Less than or equal to : =le= or <=
        - Greater than operator : =gt= or >
        - Greater than or equal to : =ge= or >=

        Example usage q=service_type==sms;organization_id==0.5.2.3\
        Example equivalent usage q=service_type==sms and organization_id==0.5.2.3

        _Querying according to RSQL syntax is possible on granted and remaining numeric fields._

        Example usage q=service_type==data;granted>=42\
        Example usage q=service_type==sms and remaining=le=42

        Note! Only one of type 'q' is allowed per request.

        _Available service_type values:_

        - service_type==sms
        - service_type==data
        - service_type==voice
        - service_type==csd
    cycleParam:
      in: query
      name: cycle
      schema:
        type: string
        x-extensible-enum:
          - current
          - previous  
        default: current
      description: |
        Cycle parameter. Selects which shared bundle consumption cycle to retrieve.

        _Available values:_

        - current
        - previous



  schemas:
    ###############################################################################
    # Object Models
    ###############################################################################

    SharedBundleSummaryResponse:
      allOf:
        - $ref: '#/components/schemas/SharedBundleSummary'
        - $ref: '#/components/schemas/SharedBundleCycle'

    SharedBundleDetailsResponse:
      allOf:
        - $ref: '#/components/schemas/SharedBundleSummary'
        - $ref: '#/components/schemas/SharedBundleDetails'
        - $ref: '#/components/schemas/SharedBundleCycle'

    SharedBundleSummary:
      type: object
      required:
        - id
        - service_type
        - granted
        - remaining
        - organization_id
      properties:
        id:
          type: string
          example: 'avagdhdcnbtdhgaf=='
          description: |
            The unique identifier for each shared bundle.
        service_type:
          type: string
          example: 'DATA'
          description: |
            The shared bundle connectivity service type.

            _Available service_type values and the corresponding unit for the shared bundle:_
            - 'DATA' (bytes)
            - 'SMS' (count)
            - 'VOICE' (seconds)
            - 'CSD' (seconds)
          x-extensible-enum: [DATA, SMS, VOICE, CSD]
        granted:
          type: integer
          example: 29000000000
          description: |
            The granted volume for the service type, positive number.
          format: int64
        remaining:
          type: integer
          example: 3468702000
          description: |
            The remaining volume for the service type, mostly positive number but may be negative if an overage has been consumed.
          format: int64
        organization_id:
          type: string
          example: 0.5.2.3
          description: |
            'organization_id' is used to filter out a single Organization.

    SharedBundleDetails:
      type: object
      required:
        - price_profile
        - level
        - type
        - updated_at
      properties:
        price_profile:
          type: string
          nullable: true
          example: 'PP0000034'
          description: |
            The Price Profile identifier that defines the shared bundle configuration.
        level:
          type: string
          example: 'COMPANY'
          description: |
            Define the commercial level the shared bundle is applied.

            _Available values:_

            - 'COMPANY'
            - 'CONTRACT'
            - 'PRICE_PROFILE'
          x-extensible-enum: [COMPANY, CONTRACT, PRICE_PROFILE]
        type:
          type: string
          example: 'FIXED'
          description: |
            This type describes how volume limitis are generated every shared bundle consumption cycle.

            _Available values:_

            - 'FIXED'
            - 'SIM_DEPENDENT'

          x-extensible-enum: [FIXED, SIM_DEPENDENT]
        updated_at:
          type: string
          format: datetime
          example: '2020-02-17T09:34:553Z'
          description: |
            The timestamp when the shared bundle information was last read from the internal backend system.

    SharedBundleCycle:
      type: object
      required:
        - cycle_started_at
        - cycle_ended_at
      properties:
        cycle_started_at:
          type: string
          format: datetime
          example: '2020-10-01T00:00:00.000Z'
          description: |
            Timestamp when the shared bundle consumption cycle is started at (inclusive).
        cycle_ended_at:
          type: string
          format: datetime
          example: '2020-11-01T00:00:00.000Z'
          description: |
            Timestamp when the shared bundle consumption cycle is (or will be) ended at (exclusive).

    ###############################################################################
    # Headers                                                                     #
    ###############################################################################
    RateLimitedResponse:
      headers:
        Content-Type:
          description: Handle Content-Type
          schema:
            type: string
        X-RateLimit-Limit-Second:
          description: The maximum number of requests allowed in a second.
          schema:
            type: integer
            format: int32
        X-RateLimit-Limit-Minute:
          description: The maximum number of requests allowed in a minute.
          schema:
            type: integer
            format: int32
        X-RateLimit-Remaining-Second:
          description: The number of requests remaining in a second.
          schema:
            type: integer
            format: int32
        X-RateLimit-Remaining-Minute:
          description: The number of requests remaining in a minute.
          schema:
            type: integer
            format: int32

    ###############################################################################
    # Error Signaling Definitions                                                 #
    ###############################################################################
    Problem:
      type: object
      properties:
        type:
          type: string
          format: uri
          description: |
            An absolute URI that identifies the problem type. When dereferenced,it SHOULD provide
            human-readable documentation for the problem type (e.g., using HTML).
          default: about:blank
          example: 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4'
        title:
          type: string
          description: |
            A short summary of the problem type in english and readable for engineers.
          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.
          example: 'Connection to database timed out.'
        instance:
          type: string
          description: An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.
          example: 'https://api.documentation.url/request-id'
  securitySchemes:
    OAuth2:
      type: oauth2
      description: The resources in the API are protected using the OAuth 2.0 protocol with the password grant flow.
      flows:
        password:
          tokenUrl: https://iot-api.aeris.com/iot/api/auth/token
          scopes:
            org-mgt.shared-bundle-consumption.read: Grant read access to shared bundle traffic consumption information.
