openapi: 3.0.0
info:
  version: '0.1'
  title: VRS Network Usage Event API
  description: |
    The VRS API Layer offers external clients a secure and reliable way to access Vodafone Roaming Services data. Built in collaboration with the DMP Networks Services Team, it ensures smooth integration with Vodafone’s internal systems. The API is fully compliant with TMF635 standards, supporting consistent and standardized data exchange across telecom platforms.
# security:
#   - BearerAuth: []
#   - Oauth2:
#       - 'usage:read'

servers:

  - url: https://api-sandbox.vf-dmp.engineering.vodafone.com/tmf-api/usageManagement/v4
    description: "Sandbox"


paths:
  # '/oauth/token':
  #   post:
  #     tags:
  #       - Authentication
  #     summary: Sign-In Endpoint
  #     description: |
  #       Authenticates a user using username and password to retrieve an access token and refresh token.
  #     operationId: getToken
      
  #     security: []  # Public endpoint
  #     parameters:
  #       - $ref: '#/components/parameters/XVfCorrelationIdParam'      
  #     requestBody:
  #       required: true
  #       content:
  #         application/x-www-form-urlencoded:
  #           schema:
  #             type: object
  #             required:
  #               - username
  #               - password
  #             properties:
  #               username:
  #                 type: string
  #                 description: User email or identifier
  #                 example: sarc.hgj@test.com
  #               password:
  #                 type: string
  #                 format: password
  #                 description: User password
  #                 example: correct_password
  #     responses:
  #       '200':
  #         description: Sign In Successful
  #         content:
  #           application/json:
  #             schema:
  #               $ref: '#/components/schemas/TokenResponse'
  #             example:
  #               access_token: "<idToken>"
  #               token_type: "Bearer"
  #               expires_in: 3600
  #               refresh_token: "<refreshToken>"
  #               id_token: "<idToken>"
  #       '400':
  #         $ref: '#/components/responses/BadRequest'
  #       '401':
  #         $ref: '#/components/responses/Unauthorized'
  #       '500':
  #         $ref: '#/components/responses/InternalServerError'

  # '/oauth/refresh':
  #   post:
  #     tags:
  #       - Authentication
  #     summary: Refresh Token Endpoint
  #     description: |
  #       Refresh tokens have higher expiry time than id_tokens. When a request comes after a longer period of time, refresh tokens provide a new id_token without signing in again.
  #     operationId: refreshToken
  #     security: [] # Public endpoint
  #     parameters:
  #       - $ref: '#/components/parameters/XVfCorrelationIdParam'
  #     requestBody:
  #       required: true
  #       content:
  #         application/x-www-form-urlencoded:
  #           schema:
  #             type: object
  #             required:
  #               - refresh_token
  #             properties:
  #               refresh_token:
  #                 type: string
  #                 description: The refresh token obtained from the Sign-In request
  #                 example: "<refreshToken>"
  #     responses:
  #       '200':
  #         description: Token Refresh Successful
  #         content:
  #           application/json:
  #             schema:
  #               $ref: '#/components/schemas/TokenResponse'
  #             example:
  #               access_token: "<new_idToken>"
  #               token_type: "Bearer"
  #               expires_in: 3600
  #               refresh_token: "<refreshToken>"
  #       '400':
  #         $ref: '#/components/responses/BadRequest'
  #       '401':
  #         $ref: '#/components/responses/Unauthorized'
  #       '500':
  #         $ref: '#/components/responses/InternalServerError'

  # '/oauth/revoke':
  #   post:
  #     tags:
  #       - Authentication
  #     summary: Revoke Token Endpoint
  #     description: |
  #       Revokes an active access token or refresh token.
  #     operationId: revokeToken
  #     security: [] # Public endpoint
  #     parameters:
  #       - $ref: '#/components/parameters/XVfCorrelationIdParam'      
  #     requestBody:
  #       required: true
  #       content:
  #         application/x-www-form-urlencoded:
  #           schema:
  #             type: object
  #             required:
  #               - token
  #             properties:
  #               token:
  #                 type: string
  #                 description: The access_token or refresh_token to be revoked.
  #                 example: "<token_to_revoke>"
  #               token_type_hint:
  #                 type: string
  #                 description: Optional hint about the type of the token submitted (access_token or refresh_token).
  #                 enum: [access_token, refresh_token]
  #     responses:
  #       '200':
  #         description: Token Revoked Successfully.
  #       '400':
  #         $ref: '#/components/responses/BadRequest'
  #       '500':
  #         $ref: '#/components/responses/InternalServerError'

  '/usage/{id}':
    get:
      tags:
        - Usage
      operationId: retrieveUsage
      description: >
          Retrieve usage data for a specific IMSI.  
          Requires a valid Bearer Token for authorization.

            **Test IMSI examples for mock responses:**  
              - Success (200 OK): 104047497196379  
              - Not Found (404): 104047497196380  
              - Invalid Value (422): 104047497196381  
              - Access Forbidden (403): 104047497196382
      # description: Retrieve usage data for a specific IMSI. Requires a valid Bearer Token. IMSI for Success 104047497196379 
      #               IMSI for notfound 104047497196380
      #               IMSI for invalidValue 104047497196381
      #               IMSI for accessForbidden 104047497196382
      security:
        # - BearerAuth: []
        - Oauth2: ['usage:read']
      parameters:
        - $ref: '#/components/parameters/XVfCorrelationIdParam'
        - name: id
          in: path
          description: IMSI / Encrypted IMSI
          required: true
          example: 104047497196379
          schema:
            type: string
        # - name: X-Customer-ID
        #   in: header
        #   description: ID of the customer (Should come from DMP Team)
        #   required: true
        #   example: CUST00002
        #   schema:
        #     type: string
      responses:
        '200':
          description: Success
          content:
            application/json;charset=utf-8:
              schema:
                $ref: '#/components/schemas/Usage'
              example:
                '@type': "Usage"
                '@baseType': "Usage"
                id: "932c-8823e4866e"
                href: "/usage/932c-8823e4866e"
                usageDate: "2020-11-20T18:07:00Z"
                usageType: "Network Usage Event"
                status: "Accepted"
                usageSpecification:
                  - id: "93c2-683ea281589"
                    name: "Network Usage Event"
                    usageSpecCharacteristic:
                    - name: "begin_period"
                      description: "Usage Begin Period"
                      valueType: "string"
                    - name: "download_active_ms_total"
                      description: "Download Active Miliseconds"
                      valueType: "string"
                    - name: "downloaded_bytes"
                      description: "Download bytes"
                      valueType: "string"
                    - name: "download_max_throughput_kbps"
                      description: "Download througput kbps"
                      valueType: "string"
                    - name: "download_throughput_mbps"
                      description: "Download throughput in Mbps"
                      valueType: "string"
                    - name: "upload_active_ms_total"
                      description: "Upload Active Miliseconds"
                      valueType: "string"
                    - name: "uploaded_bytes"
                      description: "Upload bytes"
                      valueType: "string"
                    - name: "upload_max_throughput_kbps"
                      description: "Upload throughput kbps"
                      valueType: "string"
                    - name: "upload_throughput_mbps"
                      description: "Upload throughput in Mbps"
                      valueType: "string"
                    - name: "hcountry"
                      description: "Home Country"
                      valueType: "string"
                    - name: "hmcc"
                      description: "Home Mobile Country Code"
                      valueType: "string"
                    - name: "hmnc"
                      description: "Home Mobile Network Code"
                      valueType: "string"
                    - name: "hnet"
                      description: "Home Network"
                      valueType: "string"
                    - name: "msidsntac"
                      description: "MSISDN TAC"
                      valueType: "string"
                    - name: "vcountry"
                      description: "Visited Country"
                      valueType: "string"
                    - name: "vmcc"
                      description: "Visited Mobile Country Code"
                      valueType: "string"
                    - name: "vmnc"
                      description: "Visited Mobile Network Code"
                      valueType: "string"
                    - name: "vplmn_tag"
                      description: "Visited Public Land Mobile Network"
                      valueType: "string"
                    - name: "vtadig"
                      description: "Visted TADIG"
                      valueType: "string"
                    - name: "imeitac"
                      description: "IMEI TAC"
                      valueType: "integer"
                    - name: "ratname"
                      description: "Radio Access Technology"
                      valueType: "string"
                    - name: "imsitac"
                      description: "IMSI TAC"
                      valueType: "integer"
                    - name: "data_used"
                      description: "Data used in current session if the consumer has an active session on"
                      valueType: "integer"
                usageCharacteristic:
                  - name: "apnname"
                    value: "web.vodafone.de.mnc002.mcc262.gprs"
                  - name: "celltype"
                    value: "4G"
                  - name: "handset_manufacturer"
                    value: "Apple"
                  - name: "handset_model"
                    value: "Apple iphone 15(A3090)"
                  - name: "handset_os"
                    value: "iOS"
                  - name: "begin_period"
                    value: "2025-09-10T14:12:30Z"
                  - name: "download_active_ms_total"
                    value: "2659"
                  - name: "downloaded_bytes"
                    value: "19301"
                  - name: "download_max_throughput_kbps"
                    value: "12000"
                  - name: "download_throughput_mbps"
                    value: "12"
                  - name: "upload_active_ms_total"
                    value: "5510"
                  - name: "uploaded_bytes"
                    value: "7792"
                  - name: "upload_max_throughput_kbps"
                    value: "2800"
                  - name: "upload_throughput_mbps"
                    value: "2.8"
                  - name: "hcountry"
                    value: "Germany"
                  - name: "hmcc"
                    value: "262"
                  - name: "hmnc"
                    value: "002"
                  - name: "hnet"
                    value: "Vodafone GmbH"
                  - name: "msidsntac"
                    value: "491755"
                  - name: "vcountry"
                    value: "Italy"
                  - name: "vmcc"
                    value: "222"
                  - name: "vmnc"
                    value: "010"
                  - name: "vplmn_tag"
                    value: "222/010 Italy Vodafone Italia S.p.A"
                  - name: "vtadig"
                    value: "ITAOM"
                  - name: "ratname"
                    value: "EUTRAN"
                  - name: "imeitac"
                    value: 35106958
                  - name: "imsitac"
                    value: 27291271282
                  - name: "data_used"
                    value: 107126
        '204':
          description: No Content
        '302':
          description: Found
          headers:
            Location:
              description: The URL of the new resource.
              schema:
                type: string
                format: uri
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/IMSINotInUserRange'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          $ref: '#/components/responses/UsageLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalServerError'
  '/ping':
    get:
      tags:
      - Monitoring
      summary: ping operation
      description: This operation returns if the API is alive
      operationId: healthcheckPing
      x-openapi-router-controller: app.controllers.admins_controller
      security:
        # - BearerAuth: []
        - Oauth2: ['usage:read']
      parameters:
      - $ref: '#/components/parameters/XVfCorrelationIdParam'
      responses:
        "200":
          description: ping information returned in the result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PongInfo'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
 

  # /status:
  #   get:
  #     tags:
  #     - Monitoring
  #     summary: Status operation
  #     description: This operation returns if the API is working E2E
  #     operationId: healthcheckStatus
  #     x-openapi-router-controller: app.controllers.admins_controller
  #     security:
  #       - BearerAuth: []
  #       - Oauth2: ['usage:read']
  #     parameters:
  #      - $ref: '#/components/parameters/XVfCorrelationIdParam'
  #     responses:
  #       "200":
  #         description: ping information returned in the result
  #         content:
  #           application/json:
  #             schema:
  #               $ref: '#/components/schemas/StatusInfo'
  #       '400':
  #         $ref: '#/components/responses/BadRequest'
  #       '401':
  #         $ref: '#/components/responses/Unauthorized'






components:
  parameters:
    XVfCorrelationIdParam:
      name: X-Correlator
      in: header
      description:
        The Correlation ID that will be used to allow correlation between response and corresponding request
      required: false
      example: "9e765f76-8037-4e5f-ba5d-e0c87c09a320"
      schema:
        type: string
        format: uuid
 
  securitySchemes:
    # BearerAuth:
    #   type: http
    #   scheme: bearer
    #   bearerFormat: JWT
    #   description: |
    #     Standard HTTP Bearer Token.
    #     Value: "Bearer <access_token>"
    Oauth2:
      type: oauth2
      description: |
        TMF-compliant OAuth2 security scheme.
      flows:
        clientCredentials:
          tokenUrl: /oauth2/v1/token
          scopes:
            'usage:read': Grants read access to usage data.
  schemas:
    PongInfo:
      description: Pong response object in return to a ping request
      type: object
      required:
        - suffix
        - client
        - startTime
        - endTime
        - responseTime
        - message
      properties:
        suffix:
          type: string
          description: Operation URI Path
          enum:
          - "/ping"
          example: "/ping"
        client:
          type: string
          description: Origin IP that request the operation
          example: "35.191.14.51"
          format: ipv4
        startTime:
          type: string
          description: Start time of the request in date-time format
          example: "2024-02-08T14:42:20.675Z"
          format: date-time
        endTime:
          type: string
          description: End time of the operation
          example: "2024-02-08T14:42:20.687Z"
          format: date-time
        responseTime:
          type: integer
          description: Time in miliseconds between startTime and endTime
          example: 12
        message:
          type: string
          description: Response message for the PING, that allways will be PONG
          example: PONG
          enum:
          - "PONG"
    StatusInfo:
      description: Status response object
      type: object
      required:
        - status
      properties:
        status:
          type: string
          description: The status of the API, that returns if the API is working E2E
          example: OK
          enum:
          - OK
          - KO    
    
    TokenResponse:
      type: object
      properties:
        access_token:
          type: string
          description: The access token string
        token_type:
          type: string
          description: The type of token (e.g., Bearer)
        expires_in:
          type: integer
          description: The validity lifetime of the token in seconds
        refresh_token:
          type: string
          description: Token used to refresh the access token
        id_token:
          type: string
          description: OpenID Connect ID Token (Optional in refresh response)
    Usage:
      properties:
        id:
          type: string
        href:
          type: string
        '@type':
          type: string
        '@baseType':
          type: string
        status:
          type: string
        usageType:
          type: string
        description:
          type: string
        usageDate:
          type: string
          format: date-time
        usageCharacteristic:
          type: array
          items:
            $ref: '#/components/schemas/UsageCharacteristic'
        usageSpecification:
          type: array
          items:
            $ref: '#/components/schemas/UsageSpecification'
    UsageSpecification:
      properties:
        id:
          type: string
        href:
          type: string
        '@type':
          type: string
        '@baseType':
          type: string
        name:
          type: string
        description:
          type: string
        usageSpecCharacteristic:
          type: array
          items:
            $ref: '#/components/schemas/UsageSpecCharacteristic'
    UsageCharacteristic:
      properties:
        name:
          type: string
        value:
          type: string
    UsageSpecCharacteristic:
      properties:
        '@type':
          type: string
        '@baseType':
          type: string
        name:
          type: string
        description:
          type: string
        valueType:
          type: string
    Error:
      properties:
        code:
          type: string
          description: "An application-specific error code, e.g. 'missingParameter'."
        reason:
          type: string
          description: "A human-readable explanation of the error."
        status:
          type: string
          description: "(Optional) The HTTP status code, repeated for convenience."
        referenceError:
          type: string
          format: uri
          description: "(Optional) A URI to a document describing the error."
        '@type':
          type: string
  responses:
    BadRequest:
      description: Bad request due to missing or invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "missingParameter"
            reason: "The request is missing the required X-Customer-ID header."
            status: "400"
            '@type': "Error"
    InvalidParameterType:
      description: Parameter type mismatch
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "invalidValue"
            reason: "The 'id' parameter must be a string, but a number was provided."
            status: "400"
            '@type': "Error"
    ValidationFailed:
      description: Validation failed on one or more parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "invalidValue"
            reason: "The 'id' parameter is not a valid IMSI."
            status: "422"
            '@type': "Error"
    Unauthorized:
      description: Unauthorized access
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "missingToken"
            reason: "Authentication token is missing or invalid."
            status: "401"
            '@type': "Error"
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "internalError"
            reason: "An internal server error occurred while processing the request."
            status: "500"
            '@type': "Error"
    UsageLimitExceeded:
      description: Usage limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "tooManyRequests"
            reason: "API rate limit exceeded. Please try again later."
            status: "429"
            '@type': "Error"
    IMSINotInUserRange:
      description: IMSI not in user’s allowed range
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "accessForbidden"
            reason: "Access to the requested IMSI is forbidden for this user."
            status: "403"
            '@type': "Error"
    NotFound:
      description: The requested resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: "notFound"
            reason: "The resource with the specified ID does not exist."
            status: "404"
            '@type': "Error"