diff --git a/code/API_definitions/media-streaming-rate.yaml b/code/API_definitions/media-streaming-rate.yaml new file mode 100644 index 0000000..2a5b8ed --- /dev/null +++ b/code/API_definitions/media-streaming-rate.yaml @@ -0,0 +1,575 @@ +openapi: 3.0.3 +info: + title: Media Streaming Rate + version: wip + x-camara-commonalities: 0.6 + description: | + This is a media streaming rate service API that allows application developers to retrieve + the maximum media streaming bit rate supported for a given device. + + # Introduction + The Media Streaming Rate API allows an application developer to query the network + for the maximum supported media streaming bit rate for a specific end user device. + This API measures device connection quality by determining the maximum downstream + data rate available for media streaming, which is influenced by factors such as + network conditions, device capabilities, and current network congestion. + + This information helps developers ensure their media streaming applications can provide + optimal quality while using the current network connection, enabling adaptive bitrate + streaming and preventing buffering issues. + + # API functionality + + Prerequisite: authorisation and authentication + + Usage: + 1. Request: POST `retrieve-maximum-downstream-media-rate`, passing device identification + information such as IP address, phone number, or network access identifier. + 2. Response: The network will return the maximum downstream media streaming bit rate supported + for the device along with the unit of measurement. + + # Usage in Media Streaming Applications + + This API can be integrated into media streaming applications to determine optimal + video resolution for streaming. A typical workflow: + + 1. Application client requests manifest file (DASH/HLS) from CDN server + 2. Application client calls Media Streaming Rate API to get maximum supported bit rate + 3. Based on the response, application selects appropriate media resolution from the manifest + 4. Application begins media streaming from CDN using the optimal resolution + + This approach ensures the best possible viewing experience while preventing buffering or quality issues. + + The diagram below illustrates how the Media Streaming Rate API is used in a typical media streaming application: + + ![Media Streaming Rate API Sequence Diagram](../../documentation/SupportingDocuments/media-rate-sequence-flow.png) + + # Token usage: two-legged vs three-legged + + This API supports two types of access tokens: + + - **Two-legged token**: Used for server-to-server calls. The device to be queried MUST be identified by providing the `device` object in the request body. + - **Three-legged token**: Used for user-authenticated calls. The device is identified from the access token itself, and the `device` object MUST NOT be provided in the request. + + If a two-legged token is used and the device object is missing, the API will return a `422 MISSING_IDENTIFIER` error. + If a three-legged token is used and the device object is provided, the API will return a `422 UNNECESSARY_IDENTIFIER` error. + + This approach ensures clarity and security in device identification, and aligns with CAMARA API standards. + + # Authorization and authentication + + The "Camara Security and Interoperability Profile" provides details of how an API consumer requests an access token. Please refer to Identity and Consent Management (https://github.com/camaraproject/IdentityAndConsentManagement/) for the released version of the profile. + + The specific authorization flows to be used will be agreed upon during the onboarding process, happening between the API consumer and the API provider, taking into account the declared purpose for accessing the API, whilst also being subject to the prevailing legal framework dictated by local legislation. + + In cases where personal 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 three-legged access tokens is mandatory. This ensures that the API remains in compliance with privacy regulations, upholding the principles of transparency and user-centric privacy-by-design. + + # Identifying the device from the access token + + This API requires the API consumer to identify a device as the subject of the API as follows: + - When the API is invoked using a two-legged access token, the subject will be identified from the device object, which therefore MUST be provided. + + - When a three-legged access token is used however, this optional identifier MUST NOT be provided, as the subject will be uniquely identified from the access token. + + This approach simplifies API usage for API consumers using a three-legged access token to invoke the API by relying on the information that is associated with the access token and was identified during the authentication process. + + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + +externalDocs: + description: Product documentation + url: https://github.com/camaraproject/DeviceQualityIndicator + +servers: + - url: "{apiRoot}/media-streaming-rate/wip" + variables: + apiRoot: + default: http://localhost:8087 + description: | + API root, defined by service provider, e.g. + `api.example.com` or `api.example.com/somepath` + +tags: + - name: Media Streaming Rate + description: | + Retrieve the maximum media streaming bit rate supported for a given device. + +paths: + /retrieve-maximum-downstream-media-rate: + post: + security: + - openId: + - media-streaming-rate:retrieve-maximum-downstream-media-rate + tags: + - Media Streaming Rate + summary: Get maximum downstream media streaming rate + description: | + Retrieve the maximum downstream media streaming rate for a device. This helps application + developers determine the optimal media quality settings for their applications. + + When using a two-legged token, the device object MUST be provided. + When using a three-legged token, the device object MUST NOT be provided as + the device information will be extracted from the token. + operationId: retrieveMaximumDownstreamMediaRate + parameters: + - name: x-correlator + in: header + required: false + description: Correlation id for the different services + schema: + $ref: "#/components/schemas/XCorrelator" + requestBody: + description: Device information needed to determine media rate capabilities. + content: + application/json: + schema: + $ref: "#/components/schemas/Device" + required: true + responses: + "200": + description: OK + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/MediaStreamingRateResponse" + "400": + $ref: "#/components/responses/Generic400" + "401": + $ref: "#/components/responses/Generic401" + "403": + $ref: "#/components/responses/Generic403" + "404": + $ref: "#/components/responses/Generic404" + "422": + $ref: "#/components/responses/Generic422" + "429": + $ref: "#/components/responses/Generic429" + "500": + $ref: "#/components/responses/Generic500" + +components: + securitySchemes: + openId: + type: openIdConnect + description: | + Common security scheme for all CAMARA APIs. + + Two types of tokens can be used with this API: + + 1. Two-legged token: Used for server-to-server calls where the device + information MUST be included in the request body. + + 2. Three-legged token: Used for user-authenticated calls where the device + information is extracted from the token itself. In this case, the + device object MUST NOT be included in the request. + + The specific authorization flows to be used will be agreed upon during + the onboarding process between the API consumer and the API provider. + openIdConnectUrl: https://example.com/.well-known/openid-configuration + + headers: + x-correlator: + description: Correlation id for the different services + schema: + $ref: "#/components/schemas/XCorrelator" + + schemas: + XCorrelator: + type: string + pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ + example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" + + 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` + + NOTE1: the network operator might support only a subset of these options. The + API invoker can provide multiple identifiers to be compatible across + different network operators. In this case the identifiers MUST belong to the same + device. + NOTE2: as for this Commonalities release, we are enforcing that the + networkAccessIdentifier is only part of the schema for future-proofing, + and CAMARA does not currently allow its use. After the CAMARA + meta-release work is concluded and the relevant issues are resolved, + its use will need to be explicitly documented in the guidelines. + 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 + + DeviceResponse: + description: | + An identifier for the end-user equipment able to connect to the network that the response refers to. This parameter is only returned when the API consumer includes the `device` parameter in their request (i.e. they are using a two-legged access token), and is relevant when more than one device identifier is specified, as only one of those device identifiers is allowed in the response. + + If the API consumer provides more than one device identifier in their request, and this schema is included in the response definition, the API provider MUST use it to return a single identifier which is the one they are using to fulfil the request, even if the identifiers do not match the same device. API provider does not perform any logic to validate/correlate that the indicated device identifiers match the same device. No error should be returned if the identifiers are otherwise valid to prevent API consumers correlating different identifiers with a given end user. + + allOf: + - $ref: "#/components/schemas/Device" + - maxProperties: 1 + + 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, + prefixed with '+'. + type: string + pattern: '^\+[1-9][0-9]{4,14}$' + example: "+123456789" + + 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} + + 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 + + Port: + description: TCP or UDP port number + type: integer + minimum: 0 + maximum: 65535 + + MediaStreamingRateResponse: + type: object + description: The maximum downstream media streaming bit rate supported for the device. + properties: + device: + $ref: "#/components/schemas/DeviceResponse" + maxDownstreamMediaBitRateSupported: + type: integer + description: The maximum downstream bit rate supported for the device + example: 10 + format: int32 + minimum: 0 + maximum: 1024 + unit: + type: string + description: The unit of the bit rate (e.g., Mbps, Kbps) + example: "Mbps" + enum: + - bps + - kbps + - Mbps + - Gbps + - Tbps + required: + - maxDownstreamMediaBitRateSupported + - unit + + ErrorInfo: + type: object + required: + - status + - code + - message + properties: + status: + type: integer + description: HTTP response status code + code: + type: string + description: A human-readable code to describe the error + message: + type: string + description: A human-readable description of what the event represents + + responses: + Generic400: + description: Bad Request + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 400 + code: + enum: + - INVALID_ARGUMENT + - OUT_OF_RANGE + examples: + GENERIC_400_INVALID_ARGUMENT: + description: Invalid Argument. Generic Syntax Exception + value: + status: 400 + code: INVALID_ARGUMENT + message: Client specified an invalid argument, request body or query param. + GENERIC_400_OUT_OF_RANGE: + description: Out of Range. Specific Syntax Exception used when a given field has a pre-defined range or a invalid filter criteria combination is requested + value: + status: 400 + code: OUT_OF_RANGE + message: Client specified an invalid range. + Generic401: + description: Unauthorized + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 401 + code: + enum: + - UNAUTHENTICATED + - AUTHENTICATION_REQUIRED + examples: + GENERIC_401_UNAUTHENTICATED: + description: Request cannot be authenticated and a new authentication is required + value: + status: 401 + code: UNAUTHENTICATED + message: Request not authenticated due to missing, invalid, or expired credentials. A new authentication is required. + Generic403: + description: Forbidden + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 403 + code: + enum: + - PERMISSION_DENIED + - INVALID_TOKEN_CONTEXT + examples: + GENERIC_403_PERMISSION_DENIED: + description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + value: + status: 403 + code: PERMISSION_DENIED + message: Client does not have sufficient permissions to perform this action. + GENERIC_403_INVALID_TOKEN_CONTEXT: + description: Reflect some inconsistency between information in some field of the API and the related OAuth2 Token + value: + status: 403 + code: INVALID_TOKEN_CONTEXT + message: "{{field}} is not consistent with access token." + Generic404: + description: Not found + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 404 + code: + enum: + - NOT_FOUND + - IDENTIFIER_NOT_FOUND + examples: + GENERIC_404_NOT_FOUND: + description: Resource is not found + value: + status: 404 + code: NOT_FOUND + message: The specified resource is not found. + GENERIC_404_IDENTIFIER_NOT_FOUND: + description: Some identifier cannot be matched to a device + value: + status: 404 + code: IDENTIFIER_NOT_FOUND + message: Device identifier not found. + Generic422: + description: Unprocessable Content + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 422 + code: + enum: + - SERVICE_NOT_APPLICABLE + - MISSING_IDENTIFIER + - UNSUPPORTED_IDENTIFIER + - UNNECESSARY_IDENTIFIER + examples: + GENERIC_422_SERVICE_NOT_APPLICABLE: + description: Service not applicable for the provided identifier + value: + status: 422 + code: SERVICE_NOT_APPLICABLE + message: The service is not available for the provided identifier. + GENERIC_422_MISSING_IDENTIFIER: + description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token + value: + status: 422 + code: MISSING_IDENTIFIER + message: The device cannot be identified. + GENERIC_422_UNSUPPORTED_IDENTIFIER: + description: None of the provided identifiers is supported by the implementation + value: + status: 422 + code: UNSUPPORTED_IDENTIFIER + message: The identifier provided is not supported. + GENERIC_422_UNNECESSARY_IDENTIFIER: + description: An explicit identifier is provided when a device or phone number has already been identified from the access token + value: + status: 422 + code: UNNECESSARY_IDENTIFIER + message: The device is already identified by the access token. + Generic429: + description: Too Many Requests + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 429 + code: + enum: + - QUOTA_EXCEEDED + - TOO_MANY_REQUESTS + examples: + GENERIC_429_QUOTA_EXCEEDED: + description: Request is rejected due to exceeding a business quota limit + value: + status: 429 + code: QUOTA_EXCEEDED + message: Out of resource quota. + GENERIC_429_TOO_MANY_REQUESTS: + description: Access to the API has been temporarily blocked due to rate or spike arrest limits being reached + value: + status: 429 + code: TOO_MANY_REQUESTS + message: Rate limit reached. + Generic500: + description: Internal Server Error + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 500 + code: + enum: + - INTERNAL + examples: + GENERIC_500_INTERNAL: + description: Problem in Server side. Regular Server Exception + value: + status: 500 + code: INTERNAL + message: Unknown server error. Typically a server bug. diff --git a/documentation/SupportingDocuments/MediaRateAPI_CamaraProposal-v1.pdf b/documentation/SupportingDocuments/MediaRateAPI_CamaraProposal-v1.pdf new file mode 100644 index 0000000..e4aed12 Binary files /dev/null and b/documentation/SupportingDocuments/MediaRateAPI_CamaraProposal-v1.pdf differ diff --git a/documentation/SupportingDocuments/media-rate-sequence-flow.png b/documentation/SupportingDocuments/media-rate-sequence-flow.png new file mode 100644 index 0000000..058a60d Binary files /dev/null and b/documentation/SupportingDocuments/media-rate-sequence-flow.png differ