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: sp-dvi@lists.camaraproject.org 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: "{apiRoot}/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