openapi: 3.0.3
info:
  title: CAMARA Mobile Device Identifier API
  version: 0.1.0
  description: |
    # Summary

    The Mobile Device Identifier API returns details of the mobile device (also know as the UE, or User Equipment) currently being used by a specified mobile subscriber. The following information can be returned:
     - A unique network identifier for the specific device itself (IMEI SV and IMEI)
     - A network identifier for the device make and model (IMEI Type Allocation Code)
     - Device manufacturer name and model

     This information can be useful in a number of scenarios, such as the following:
     - For insurance purposes, to automatically identify a device that a customer wishes to insure
     - For security / fraud reasons, to establish that a customer is not using a device they claim to have broken or lost
     - For service delivery reasons, to optimise content for a particular device or OS type

    # Introduction

    Mobile devices are allocated a unique identity by the manufacturer, known as the International Mobile Equipment Identity, or IMEI. The current software version (SV) of the device can be appended to this, in which case the identifier is known as the IMEI SV. This identity is signalled to the mobile network when the device connects, both to confirm that the device is not blocked, and also allow device dependent network configurations to be implemented.

    The IMEI is a 15 digit integer, and the IMEI SV is a 16 digit integer:
    - The first 8 digits are known as the Type Allocation Code (TAC), and identify the manufacturer and model of the device
    - The following 6 digits are the serial number of the device for that TAC
    - For IMEI, the remaining digit is a check digit
    - For IMEI SV, the remaining two digits are the software version

    TACs are issued and managed by the GSMA, and can be queried using the [GSMA IMEI database](https://www.gsma.com/aboutus/workinggroups/terminal-steering-group/imei-database).

    The mobile network associates this device identifier with the mobile subscription currently using the device. The mobile subscription is defined by the Subscriber Identity Module (SIM) currently active in the mobile device. This may be a removable SIM or an eSIM. In either case, it is possible for the association between the device identifier and subscription to change - for example, when a physical SIM is transferred to another mobile device.

    ![Device Identifier API Overview](https://raw.githubusercontent.com/camaraproject/DeviceIdentifier/main/documentation/API_documentation/resources/Device_Identifier_Overview.png)

    The Device Identifier API allows the API consumer to obtain the IMEI and associated parameters for a specified mobile subscription identifier or equivalent. The mobile subscription can be identified using one of the following subscription identifiers:
    - the subscription phone number (also known as MSISDN)
    - the subscription network access identifier, which is a domain specific identifier typically allocated to devices that do not require voice / SMS connectivity
    - the current IP address and port alloacted to the device, which must be an IPv6 or public IPv4 address

    The API can be called by an application server or other 3rd party server to establish the identity of the device currently being used by the mobile subscription. The information returned will depend upon the consent that the end user (i.e. mobile subscription owner) has given for that information to be provided to the API consumer. For example, if the end user has not consented to any information about their device being given, then the API consumer will receive an error in reponse to their request. Otherwise, the information that the end user has consented to being given will be returned.

    # Relevant terms and definitions

    ### Device Identifier API service endpoint
    The URL pointing to the RESTful resource of the Device Identifier API.

    ### Identifier for the mobile subscription
    At least one identifier for the mobile subscription from the following four options:
      - Phone number (i.e. MSISDN)
      - Network Access Identifier assigned by the mobile network operator for the device
      - IPv6 address
      - IPv4 address

    In scenarios where a primary MSISDN is shared between multiple devices, each of which has its own "secondary" MSISDN (e.g. OneNumber), the MSISDN passed by the API consumer will be treated as the secondary MSISDN, and hence the identifier returned will be that of the relevant associated device (such as a smartwatch). In such scenarios, the "primary" device (e.g. smartphone) is usually allocated the same primary and secondary MSISDN, and hence providing the primary MSISDN will always return the identity of the primary device and not any associated devices.

    ### Authorization and authentication

    CAMARA guidelines defines a set of authorization flows which can grant API clients access to the API functionality, as outlined in the document [CAMARA-API-access-and-user-consent.md](https://github.com/camaraproject/IdentityAndConsentManagement/blob/main/documentation/CAMARA-API-access-and-user-consent.md). Which specific authorization flows are to be used will be determined during onboarding process, happening between the API Client and the Telco Operator exposing the API, taking into account the declared purpose for accessing the API, while also being subject to the prevailing legal framework dictated by local legislation.

    It is important to remark that in cases where personal user data is processed by the API, and users can exercise their rights through mechanisms such as opt-in and/or opt-out, the use of 3-legged access tokens becomes mandatory. This measure ensures that the API remains in strict compliance with user privacy preferences and regulatory obligations, upholding the principles of transparency and user-centric data control.

    # API functionality

    The API defines two service endpoints:

    - `POST /retrieve-identifier` to get details about the specific device being used by a given mobile subscriber, including IMEI / IMEISV and the type of device
    - `POST /retrieve-type` to get details only about the type (i.e. manufacturer and model) of device being used by a given mobile subscriber

    To call either of these endpoints, the API consumer must first obtain a valid OAuth2 token from the token endpoint, which is then passed as an Authorization header. The API consumer must also pass at least one of the available mobile subscription identifiers in the body of the request.

    Not all possible mobile subscription identifiers may be valid for a given network or implementation, and hence the API consumer should provide as many identifiers as are known to them. If the API consumer provides identifiers for different mobile subscriptions, the API may return an error, or it may take each identifier provided in the order specified above until it finds a valid subscription identifier.

    If the authentication token is not valid, a `401 UNAUTHENTICATED` error is returned

    If the mobile subscription parameters contain a formatting error, a `400 INVALID_ARGUMENT` error is returned.

    If the mobile subscription cannot be identified from the provided parameters, a `404 NOT_FOUND` error is returned.

    If the end user has not consented to the API consumer getting access to the device identifier information, then a `403 PERMISSION_DENIED` error is returned.

    Otherwise, a JSON object is returned containing the data the the end user has consented to sharing with the API consumer.
    - When calling endpoint `retrieve-identifier`, the response will always contain `imei`
    - When calling endpoint `retrieve-type`, the response will always contain `tac`
    - Responses will also always contain a `lastChecked` field, indicating when the information provided was last confirmed to be correct
    - Other response parameters are implementation dependent

    An example of a JSON response object is as follows:
    ```
    {
       "lastChecked": "2024-02-20T10:41:38.657Z",
       "imeisv": "49015420323751800",
       "imei": "4901542032375181",
       "tac": "49015420",
       "model": "3110",
       "manufacturer": "Nokia"
    }
    ```

    # Further info and support

    (FAQs will be added in a later version of the documentation)

  contact:
    email: contact@spryfoxnetworks.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html

externalDocs:
  description: Product documentation at CAMARA
  url: https://github.com/camaraproject/DeviceIdentifier

servers:
  - url: "https://labs-api.spryfoxnetworks.com/qpcloud-monet-swagger/device-identifier/v0.1.0"
    variables:
      apiRoot:
        default: https://localhost:443
        description: API root

paths:
  "/retrieve-identifier":
    post:
      summary: Get details about the specific device being used by a given mobile subscriber
      description: Get details about the specific device being used by a given mobile subscriber
      operationId: retrieveIdentifier
      tags:
        - Get Device Identifiers
      security:
        - openId:
            - device-identifier:retrieve-identifier

      parameters:
        - in: header
          name: X-Correlator
          required: false
          schema:
            type: string
            format: uuid

      requestBody:
        description: Parameters to create a new session
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Device"

      responses:
        "200":
          $ref: '#/components/responses/200RetrieveIdentifier'
        "400":
          $ref: '#/components/responses/400BadRequest'
        "401":
          $ref: '#/components/responses/401Unauthorized'
        "403":
          $ref: '#/components/responses/403Forbidden'
        "404":
          $ref: '#/components/responses/404NotFound'
        "405":
          $ref: '#/components/responses/405MethodNotAllowed'
        "406":
          $ref: '#/components/responses/406Unacceptable'
        "429":
          $ref: '#/components/responses/429TooManyRequests'
        "500":
          $ref: '#/components/responses/500InternalServerError'
        "502":
          $ref: '#/components/responses/502BadGateway'
        "503":
          $ref: '#/components/responses/503ServiceUnavailable'
        "504":
          $ref: '#/components/responses/504GatewayTimeout'

  "/retrieve-type":
    post:
      summary: Get details about the type of device being used by a given mobile subscriber
      description: Get details about the type of device being used by a given mobile subscriber
      operationId: retrieveType
      tags:
        - Get Device Identifiers
      security:
        - openId:
            - device-identifier:retrieve-type

      parameters:
        - in: header
          name: X-Correlator
          required: false
          schema:
            type: string
            format: uuid

      requestBody:
        description: Parameters to create a new session
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Device"

      responses:
        "200":
          $ref: '#/components/responses/200RetrieveType'
        "400":
          $ref: '#/components/responses/400BadRequest'
        "401":
          $ref: '#/components/responses/401Unauthorized'
        "403":
          $ref: '#/components/responses/403Forbidden'
        "404":
          $ref: '#/components/responses/404NotFound'
        "405":
          $ref: '#/components/responses/405MethodNotAllowed'
        "406":
          $ref: '#/components/responses/406Unacceptable'
        "429":
          $ref: '#/components/responses/429TooManyRequests'
        "500":
          $ref: '#/components/responses/500InternalServerError'
        "502":
          $ref: '#/components/responses/502BadGateway'
        "503":
          $ref: '#/components/responses/503ServiceUnavailable'
        "504":
          $ref: '#/components/responses/504GatewayTimeout'

components:
  securitySchemes:
    openId:
      type: openIdConnect
      openIdConnectUrl: .well-known/openid-configuration

  headers:
    X-Correlator:
      description: Correlation id for the different services
      required: false
      schema:
        type: string
        format: uuid

  responses:
    200RetrieveIdentifier:
      description: An device identifier has been found for the specified subscriber
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            required:
              - lastChecked
              - imei
            allOf:
              - $ref: "#/components/schemas/LastChecked"
              - $ref: "#/components/schemas/DeviceIdentifier"
              - $ref: "#/components/schemas/DeviceType"

    200RetrieveType:
      description: An device identifier has been found for the specified subscriber
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            required:
              - lastChecked
              - tac
            allOf:
              - $ref: "#/components/schemas/LastChecked"
              - $ref: "#/components/schemas/DeviceType"

    400BadRequest:
      description: Bad Request
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            InsufficientParameters:
              description: Sufficient parameters must be provided to allow the target UE to be identified
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: "At least one of phoneNumber, networkAccessIdentifier, ipv4Address and ipv6Address must be specified"
            InconsistentDeviceProperties:
              description: Device parameters provided identify different devices
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: "Multiple inconsistent device parameters specified"
            InvalidExternalId:
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: "Invalid format: networkAccessIdentifier"
            InvalidMSISDN:
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: "Invalid format: phoneNumber"
            InvalidIPv4:
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: "Invalid format: ipv4Address"
            InvalidIPv6:
              value:
                status: 400
                code: INVALID_ARGUMENT
                message: "Invalid format: ipv6Address"
            InvalidPort:
              value:
                status: 400
                code: OUT_OF_RANGE
                message: "Invalid value: ipv4Address.publicPort"
    401Unauthorized:
      description: Unauthorized
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            InvalidCredentials:
              value:
                status: 401
                code: UNAUTHENTICATED
                message: "Request not authenticated due to missing, invalid, or expired credentials"

    403Forbidden:
      description: Forbidden
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            InsufficientPermissions:
              value:
                status: 403
                code: PERMISSION_DENIED
                message: "API consumer does not have sufficient permissions to perform this action"

    404NotFound:
      description: Subscriber Not Found
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            SubscriberNotFound:
              description: The specified parameters are either inconsistent (if multiple parameters are specified) or not currently associated with any customers of this service
              value:
                status: 404
                code: NOT_FOUND
                message: "No device found for the specified parameters"

    405MethodNotAllowed:
      description: Method Not Allowed
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            MethodNotAllowed:
              description: An HTTP verb other than GET has been used to try and access the resource
              value:
                status: 404
                code: METHOD_NOT_ALLOWED
                message: "The request method is not supported by this resource"

    406Unacceptable:
      description: Not Acceptable
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            NotAcceptable:
              description: A response format other than JSON has been requested
              value:
                status: 406
                code: NOT_ACCEPTABLE
                message: "The server cannot produce a response matching the content requested by the client through Accept-* headers"

    429TooManyRequests:
      description: Too Many Requests
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            TooManyRequests:
              description: Access to the API has been temporarily blocked due to quota or spike arrest limits being reached
              value:
                status: 429
                code: TOO_MANY_REQUESTS
                message: "Either out of resource quota or reaching rate limiting"

    500InternalServerError:
      description: Internal Server Error
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 500
            code: INTERNAL
            message: "The service is currently not available"

    502BadGateway:
      description: Bad Gateway
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 502
            code: BAD_GATEWAY
            message: "The service is currently not available"

    503ServiceUnavailable:
      description: Service Unavailable
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 503
            code: UNAVAILABLE
            message: "The service is currently not available"

    504GatewayTimeout:
      description: Gateway Time-Out
      headers:
        X-Correlator:
          $ref: "#/components/headers/X-Correlator"
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 504
            code: TIMEOUT
            message: "The service is currently not available"

  schemas:
    LastChecked:
      description: |
        Last time that the associated device identity was checked and, if necessary, updated
      properties:
        lastChecked:
          description: Date and time information was last checked
          type: string
          format: date-time
          example: "2024-02-20T10:41:38.657Z"

    DeviceIdentifier:
      description: |
        The individual physical mobile device identifier, as expressed by the IMEI and IMEISV
      type: object
      properties:
        imeisv:
          type: string
          description: IMEISV of the device
          example: "49015420323751800"
        imei:
          type: string
          description: IMEI of the device
          example: "4901542032375181"

    DeviceType:
      description: |
        The physical device type, as expressed by Type Approval Code, manufacturer name and model name
      type: object
      properties:
        tac:
          type: string
          description: IMEI TAC of the device
          example: "49015420"
        model:
          type: string
          description: Model of the device
          example: "3110"
        manufacturer:
          type: string
          description: Manufacturer of the device
          example: "Nokia"

    Device:
      description: |
        End-user equipment able to connect to a mobile network. Examples of devices include smartphones or IoT sensors/actuators.
        The developer can choose to provide the below specified device identifiers:
        * `ipv4Address`
        * `ipv6Address`
        * `phoneNumber`
        * `networkAccessIdentifier`
        NOTE: the MNO might support only a subset of these options. The API invoker can provide multiple identifiers to be compatible across different MNOs. In this case the identifiers MUST belong to the same device.
      type: object
      properties:
        phoneNumber:
          $ref: "#/components/schemas/PhoneNumber"
        networkAccessIdentifier:
          $ref: "#/components/schemas/NetworkAccessIdentifier"
        ipv4Address:
          $ref: "#/components/schemas/DeviceIpv4Addr"
        ipv6Address:
          $ref: "#/components/schemas/DeviceIpv6Address"
      minProperties: 1

    DeviceIpv4Addr:
      type: object
      description: |
        The device should be identified by either the public (observed) IP address and port as seen by the application server, or the private (local) and any public (observed) IP addresses in use by the device (this information can be obtained by various means, for example from some DNS servers).

        If the allocated and observed IP addresses are the same (i.e. NAT is not in use) then  the same address should be specified for both publicAddress and privateAddress.

        If NAT64 is in use, the device should be identified by its publicAddress and publicPort, or separately by its allocated IPv6 address (field ipv6Address of the Device object)

        In all cases, publicAddress must be specified, along with at least one of either privateAddress or publicPort, dependent upon which is known. In general, mobile devices cannot be identified by their public IPv4 address alone.
      properties:
        publicAddress:
          $ref: "#/components/schemas/SingleIpv4Addr"
        privateAddress:
          $ref: "#/components/schemas/SingleIpv4Addr"
        publicPort:
          $ref: "#/components/schemas/Port"
      anyOf:
        - required: [publicAddress, privateAddress]
        - required: [publicAddress, publicPort]
      example:
        {
          "publicAddress": "84.125.93.10",
          "publicPort": 59765
        }

    ErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: A short, human-readable summary of the problem type
        status:
          type: integer
          description: The HTTP status code
        message:
          type: string
          description: This parameter appears when there was an error. Human readable explanation specific to this occurrence of the problem

    NetworkAccessIdentifier:
      description: A public identifier addressing a subscription in a mobile network. In 3GPP terminology, it corresponds to the GPSI formatted with the External Identifier ({Local Identifier}@{Domain Identifier}). Unlike the telephone number, the network access identifier is not subjected to portability ruling in force, and is individually managed by each operator.
      type: string
      example: "123456789@domain.com"

    PhoneNumber:
      description: A public identifier addressing a telephone subscription. In mobile networks it corresponds to the MSISDN (Mobile Station International Subscriber Directory Number). In order to be globally unique it has to be formatted in international format, according to E.164 standard, optionally prefixed with '+'.
      type: string
      pattern: '^\+?[0-9]{5,15}$'
      example: "123456789"

    Port:
      description: TCP or UDP port number
      type: integer
      minimum: 1024
      maximum: 65535

    SingleIpv4Addr:
      description: A single IPv4 address with no subnet mask
      type: string
      format: ipv4
      example: "84.125.93.10"

    DeviceIpv6Address:
      description: |
        The device should be identified by the observed IPv6 address, or by any single IPv6 address from within the subnet allocated to the device (e.g. adding ::0 to the /64 prefix).
      type: string
      format: ipv6
      example: 2001:db8:85a3:8d3:1319:8a2e:370:7344
