openapi: 3.0.3
info:
title: Global System for Mobile Communications GSMA Camara Project Population Density Data
description: >-
Population Density Data API exposes population density estimations for a
specified area for a specified time interval.
# Introduction
With the Population Density Data API the customer can retrieve population
density estimations for a specific area at the current or a future period of
time. The estimation considers historical anonymized information of the
network connected devices in the requested area.
This functionality can be used for multiple use cases, some of the possible
use cases for this API are:
- Supporting BVLOS (Beyond Visual Line of Sight) flights with the
information needed to meet SORA 2.5 (Specific Operation Risk Assessment)
requirements in terms of intrinsic Ground Risk Class (iGRC). More
information in [Specific Operations Risk
Assessment](https://www.easa.europa.eu/en/domains/civil-drones-rpas/specific-category-civil-drones/specific-operations-risk-assessment-sora)
- Providing information to identify if the ground risk class for a given
drone flight path is acceptable for the time of the flight, or an
alternative time should be considered to lower the risk.
- Sustainable Urban Planning.
- Environmental monitoring at mass events, such as concerts or festivals.
The list above is just a few examples, the API can be used for other use
cases as well.
# Relevant terms and definitions
* **Population Density**: refers to the number of people in a given area
divided by the total size of the area.
* **Notification URL and token**: Developers may provide a callback URL
(`sink`) for receiving an async response. This is an optional parameter. If
`sink` is included, it is RECOMMENDED for the client to provide as well the
`sinkCredential` property to protect the notification endpoint. In the
current version,`sinkCredential.credentialType` MUST be set to `ACCESSTOKEN`
if provided.
# API Functionality
Once a developer specifies (1) the area as a polygon shape, (2) a precision
level and (3) time interval in which they want to obtain the population
density, the API returns a data set consisting of a sequence of time ranges,
with each time range containing the input polygon subdivided into
equal-sized grid cells.
For each of the equal-sized cells of the grid, an estimated population
density is reported for each time slot within the range, this includes:
estimated population density people/km2, and a range for this estimation -
[minimum, maximum] (exact definitions of minimum and maximum are estimation
algorithm specific).
These values are calculated based on historical data and/or prediction
models trained on such data.
The polygon specifying an area of interest must comply with certain
restrictions, which must be previously validated by the developer:
- The polygon may not exceed a certain area.
- The polygon may not contain more than 15 vertexes.
- The polygon must be associated with a location where the MNO provides
mobile connectivity services. If a polygon is located entirely outside the
supported area, an empty array is returned.
The standard behaviour of the API is synchronous, although for large area
requests the API may behave asynchronously. An API invoker can enforce
asynchronous behaviour by providing a callback URL (`sink`) is in the
request, in this case the API sends a callback to the callback URL provided
with the result of the request. If `sink` is included, it is RECOMMENDED for
the client to provide as well the `sinkCredential` property to protect the
notification endpoint. In the current
version,`sinkCredential.credentialType` MUST be set to `ACCESSTOKEN` if
provided.
For requests with a combination of `area`, `precision`, `startDate` and
`endDate` properties involving an amount of processing that cannot be
processed synchronously, the API returns the error response
`POPULATION_DENSITY_DATA.UNSUPPORTED_SYNC_RESPONSE`.
For requests with a combination of `area`, `precision`, `startDate` and
`endDate` properties too big for both synchronous and asynchronous
processing, the API returns the error response
`POPULATION_DENSITY_DATA.UNSUPPPORTED_REQUEST`.
**NOTE**: In order to ensure anonymized information, if the data relating to
a grid cell in the required time interval is not sufficient to be exposed
due to [k-anonymity](https://en.wikipedia.org/wiki/K-anonymity), no such
data is returned by the API and the value of the dataType property is
`LOW_DENSITY`.
# Resources and Operations overview
The API provides one endpoint that accepts POST requests for retrieving
population density information in the specified area.
# Authorization and Authentication
The "Camara Security and Interoperability Profile" provides details on how a
client requests an access token. Please refer to Identify and Consent
Management (https://github.com/camaraproject/IdentityAndConsentManagement/)
for the released version of the Profile.
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.
Population Density Data API ensures the usage of anonymized information and
do not treat personal data neither as input nor output. Therefore, the
access to Population Density Data API is defined as Client Credentials -
2-legged. Please refer to Identify and Consent Management
(https://github.com/camaraproject/IdentityAndConsentManagement/) for the
latest detailed specification of this authentication/authorization flow.
# Further info and support
(FAQs will be added in a later version of the documentation)
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
version: 0.1.1
x-camara-commonalities: 0.4.0
externalDocs:
description: Product documentation at Camara.
url: https://github.com/camaraproject/
servers:
- url: '{apiRoot}/population-density-data/v0.1'
variables:
apiRoot:
default: http://localhost:9091
description: API root
tags:
- name: Population Density Data
description: Operations to retrieve population density information.
paths:
/retrieve:
post:
tags:
- Population Density Data
summary: Global System for Mobile Communications Retrieves population density information in a specified area
description: >-
Retrieves population density estimation together with the estimation
range related for a time slot for a given area (described as a polygon)
as a data set consisting of a sequence of equally-sized objects covering
the input polygon area.
operationId: retrievePopulationDensity
parameters:
- $ref: '#/components/parameters/x-correlator'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PopulationDensityRequest'
example:
area:
areaType: POLYGON
boundary:
- latitude: 45.754114
longitude: 4.860374
- latitude: 45.753845
longitude: 4.863185
- latitude: 45.75249
longitude: 4.861876
- latitude: 45.751224
longitude: 4.861125
- latitude: 45.751442
longitude: 4.859827
startDate: '2024-04-23T14:44:18.165Z'
endDate: '2024-04-23T14:44:18.165Z'
precision: 7
required: true
callbacks:
populationDensityDataCallback:
'{$request.body#/sink}':
post:
tags:
- Population Density Data
summary: Population Density Data callback
description: >
Important: this endpoint is to be implemented by the API
consumer.
The Population Density Data server will call this endpoint when
the request result is ready.
operationId: postNotification
parameters:
- $ref: '#/components/parameters/x-correlator'
requestBody:
description: Population density data result.
content:
application/json:
schema:
$ref: '#/components/schemas/PopulationDensityResponse'
examples:
PopulationDensitySupportedAreaResponseExample:
$ref: >-
#/components/examples/PopulationDensitySupportedAreaResponseExample
PopulationDensityAreaNotSupportedResponseExample:
$ref: >-
#/components/examples/PopulationDensityAreaNotSupportedResponseExample
PopulationDensityPartOfAreaNotSupportedResponseExample:
$ref: >-
#/components/examples/PopulationDensityPartOfAreaNotSupportedResponseExample
responses:
'204':
description: Successful notification
headers:
x-correlator:
$ref: '#/components/headers/x-correlator'
'400':
$ref: '#/components/responses/Generic400'
'401':
$ref: '#/components/responses/Generic401'
'403':
$ref: '#/components/responses/Generic403'
'410':
$ref: '#/components/responses/Generic410'
'500':
$ref: '#/components/responses/Generic500'
'503':
$ref: '#/components/responses/Generic503'
security:
- {}
- notificationsBearerAuth: []
responses:
'200':
description: Population density data result.
headers:
x-correlator:
$ref: '#/components/headers/x-correlator'
content:
application/json:
schema:
$ref: '#/components/schemas/PopulationDensityResponse'
examples:
PopulationDensitySupportedAreaResponseExample:
$ref: >-
#/components/examples/PopulationDensitySupportedAreaResponseExample
PopulationDensityAreaNotSupportedResponseExample:
$ref: >-
#/components/examples/PopulationDensityAreaNotSupportedResponseExample
PopulationDensityPartOfAreaNotSupportedResponseExample:
$ref: >-
#/components/examples/PopulationDensityPartOfAreaNotSupportedResponseExample
'202':
description: >-
Population density data requested. This response is returned when
the behaviour of the API is asynchronous.
headers:
x-correlator:
$ref: '#/components/headers/x-correlator'
'400':
$ref: '#/components/responses/RetrieveLocationBadRequest400'
'401':
$ref: '#/components/responses/Generic401'
'403':
$ref: '#/components/responses/Generic403'
'404':
$ref: '#/components/responses/Generic404'
'500':
$ref: '#/components/responses/Generic500'
'503':
$ref: '#/components/responses/Generic503'
security:
- openId:
- population-density-data:read
components:
securitySchemes:
openId:
type: openIdConnect
openIdConnectUrl: https://example.com/.well-known/openid-configuration
notificationsBearerAuth:
description: Bearer authentication for notifications
type: http
scheme: bearer
bearerFormat: '{$request.body#sinkCredential.credentialType}'
headers:
x-correlator:
description: Correlation id for the different services.
schema:
type: string
parameters:
x-correlator:
name: x-correlator
in: header
description: Correlation id for the different services.
schema:
type: string
schemas:
PopulationDensityRequest:
type: object
description: >-
Request object for retrieving population density data in a specified
area. **NOTE**: The difference between `startDate` and `endDate` cannot
be greater than 7 days.
properties:
area:
$ref: '#/components/schemas/Area'
startDate:
type: string
format: date-time
description: >-
Start date time. It must follow [RFC
3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and
must have time zone. Recommended format is
yyyy-MM-dd'T'HH:mm:ss.SSSZ (i.e. which allows
2023-07-03T14:27:08.312+02:00 or 2023-07-03T12:27:08.312Z) The
minimum startDate is the time of the request.
endDate:
type: string
format: date-time
description: >-
End date time. It must follow [RFC
3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and
must have time zone. Recommended format is
yyyy-MM-dd'T'HH:mm:ss.SSSZ (i.e. which allows
2023-07-03T14:27:08.312+02:00 or 2023-07-03T12:27:08.312Z) The
maximum endDate allowed is 3 months from the time of the request.
precision:
type: integer
description: >-
Precision required of response cells. Precision defines a geohash
level and corresponds to the length of the geohash for each cell.
More information at [Geohash
system](https://en.wikipedia.org/wiki/Geohash)" If not included the
default precision level 7 is used by default. In case of using a not
supported level by the MNO, the API returns the error response
`POPULATION_DENSITY_DATA.UNSUPPORTED_PRECISION`.
minimum: 1
maximum: 12
default: 7
sink:
type: string
format: url
description: >-
The address to which events about all status changes of the session
(e.g. session termination) shall be delivered, using the HTTP
protocol.
example: https://endpoint.example.com/sink
sinkCredential:
description: >-
A sink credential provides authentication or authorization
information necessary to enable delivery of events to a target.
allOf:
- $ref: '#/components/schemas/SinkCredential'
required:
- area
- startDate
- endDate
Area:
type: object
properties:
areaType:
$ref: '#/components/schemas/AreaType'
required:
- areaType
discriminator:
propertyName: areaType
mapping:
POLYGON: '#/components/schemas/Polygon'
AreaType:
type: string
description: |
Type of this area.
POLYGON - The area is defined as a polygon.
enum:
- POLYGON
Polygon:
allOf:
- $ref: '#/components/schemas/Area'
- type: object
required:
- boundary
properties:
boundary:
$ref: '#/components/schemas/PointList'
PointList:
type: array
items:
$ref: '#/components/schemas/Point'
minItems: 3
maxItems: 15
Point:
type: object
description: Coordinates (latitude, longitude) defining a location in a map
required:
- latitude
- longitude
properties:
latitude:
$ref: '#/components/schemas/Latitude'
longitude:
$ref: '#/components/schemas/Longitude'
example:
latitude: 50.735851
longitude: 7.10066
Latitude:
description: Latitude component of a location.
type: number
format: double
minimum: -90
maximum: 90
Longitude:
description: Longitude component of location.
type: number
format: double
minimum: -180
maximum: 180
SinkCredential:
type: object
properties:
credentialType:
type: string
enum:
- PLAIN
- ACCESSTOKEN
- REFRESHTOKEN
description: >-
The type of the credential. With the current API version the type
MUST be set to `ACCESSTOKEN`
discriminator:
propertyName: credentialType
mapping:
PLAIN: '#/components/schemas/PlainCredential'
ACCESSTOKEN: '#/components/schemas/AccessTokenCredential'
REFRESHTOKEN: '#/components/schemas/RefreshTokenCredential'
required:
- credentialType
PlainCredential:
type: object
description: A plain credential as a combination of an identifier and a secret.
allOf:
- $ref: '#/components/schemas/SinkCredential'
- type: object
required:
- identifier
- secret
properties:
identifier:
description: The identifier might be an account or username.
type: string
secret:
description: The secret might be a password or passphrase.
type: string
AccessTokenCredential:
type: object
description: An access token credential.
allOf:
- $ref: '#/components/schemas/SinkCredential'
- type: object
properties:
accessToken:
description: >-
REQUIRED. An access token is a previously acquired token
granting access to the target resource.
type: string
accessTokenExpiresUtc:
type: string
format: date-time
description: >-
REQUIRED. An absolute UTC instant at which the token shall be
considered expired.
accessTokenType:
description: >-
REQUIRED. Type of the access token (See [OAuth
2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). For the
current version of the API the type MUST be set to `Bearer`.
type: string
enum:
- bearer
required:
- accessToken
- accessTokenExpiresUtc
- accessTokenType
RefreshTokenCredential:
type: object
description: An access token credential with a refresh token.
allOf:
- $ref: '#/components/schemas/SinkCredential'
- type: object
properties:
accessToken:
description: >-
REQUIRED. An access token is a previously acquired token
granting access to the target resource.
type: string
accessTokenExpiresUtc:
type: string
format: date-time
description: >-
REQUIRED. An absolute UTC instant at which the token shall be
considered expired.
accessTokenType:
description: >-
REQUIRED. Type of the access token (See [OAuth
2.0](https://tools.ietf.org/html/rfc6749#section-7.1)).
type: string
enum:
- bearer
refreshToken:
description: >-
REQUIRED. An refresh token credential used to acquire access
tokens.
type: string
refreshTokenEndpoint:
type: string
format: uri
description: >-
REQUIRED. A URL at which the refresh token can be traded for an
access token.
required:
- accessToken
- accessTokenExpiresUtc
- accessTokenType
- refreshToken
- refreshTokenEndpoint
PopulationDensityResponse:
type: object
description: >-
Population density values is represented in time intervals for
different cells of the requested area. Each element in
`timedPopulationDensityData` array corresponds to a time interval,
containing population density data for the grid cells. The intervals are
1 hour long.
properties:
timedPopulationDensityData:
type: array
description: >-
Time ranges along with the population density data for the cells
within it.
The request startDate or the request endDate have to be fully covered by the intervals.
For example, if the intervals are 1-hour long and the input date range were [2024-01-03T11:25:00Z
to 2024-01-03T12:45:00Z] it would contain 2 intervals (Interval from 2024-01-03T11:00:00Z
to 2024-01-03T12:00:00Z and interval from 2024-01-03T12:00:00Z to 2024-01-03T13:00:00Z).
items:
$ref: '#/components/schemas/TimedPopulationDensityData'
status:
$ref: '#/components/schemas/ResponseStatus'
required:
- timedPopulationDensityData
- status
ResponseStatus:
type: string
description: >-
Represents the state of the response for the input polygon defined in
the request, the possible values are:
- `SUPPORTED_AREA`: The whole request area is supported. Population density data for the entire requested area is returned.
- `PART_OF_AREA_NOT_SUPPORTED`: Part of the requested area is outside the MNOs coverage area, the cells outside the coverage
area will have property `dataType` with value `NO_DATA`.
- `AREA_NOT_SUPPORTED`: The whole requested area is outside the MNOs coverage area. No data will be returned.
enum:
- SUPPORTED_AREA
- PART_OF_AREA_NOT_SUPPORTED
- AREA_NOT_SUPPORTED
TimedPopulationDensityData:
type: object
properties:
startTime:
type: string
format: date-time
description: >-
Interval start time. It must follow [RFC
3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and
must have time zone. Recommended format is
yyyy-MM-dd'T'HH:mm:ss.SSSZ (i.e. which allows
2023-07-03T14:27:08.312+02:00 or 2023-07-03T12:27:08.312Z)
endTime:
type: string
format: date-time
description: >-
Interval end time. It must follow [RFC
3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and
must have time zone. Recommended format is
yyyy-MM-dd'T'HH:mm:ss.SSSZ (i.e. which allows
2023-07-03T14:27:08.312+02:00 or 2023-07-03T12:27:08.312Z)
example: '2024-01-03T13:00:00Z'
cellPopulationDensityData:
$ref: '#/components/schemas/CellPopulationDensityDataArray'
required:
- startTime
- endTime
- cellPopulationDensityData
CellPopulationDensityDataArray:
type: array
description: >-
Population density data for the different cells in a concrete time
range.
items:
$ref: '#/components/schemas/CellPopulationDensityData'
minItems: 1
CellPopulationDensityData:
type: object
description: Population density data of a cell in a concrete time range.
properties:
geohash:
type: string
description: >-
Coordinates of the cell represented as a string using the [Geohash
system](https://en.wikipedia.org/wiki/Geohash). Encoding a
geographic location into a short string. The value length, and thus,
the cell granularity, is determined by the request body property
`precision`.
example: ezdmemd
populationDensityData:
$ref: '#/components/schemas/PopulationDensityData'
required:
- geohash
- populationDensityData
PopulationDensityData:
description: >-
Object that contains the estimated population density and an estimation
range in a cell for a specific time interval. In case of insufficient
data to guarantee an anonymized prediction due to the k-anonymity within
a specific cell and time range, no population density data is returned
and the property `dataType` value is "LOW_DENSITY". In case of a cell
not supported `dataType` value is "NO_DATA"
properties:
dataType:
type: string
enum:
- NO_DATA
- LOW_DENSITY
- DENSITY_ESTIMATION
required:
- dataType
discriminator:
propertyName: dataType
mapping:
NO_DATA: '#/components/schemas/PopulationDensityData'
LOW_DENSITY: '#/components/schemas/PopulationDensityData'
DENSITY_ESTIMATION: '#/components/schemas/DensityEstimationPopulationDensityData'
DensityEstimationPopulationDensityData:
allOf:
- $ref: '#/components/schemas/PopulationDensityData'
- type: object
properties:
maxPplDensity:
type: number
format: double
description: Maximum people/km2 estimated for the defined area.
minPplDensity:
type: number
format: double
description: Minimum people/km2 estimated for the defined area.
pplDensity:
type: number
format: double
description: people/km2 estimation for the defined area.
required:
- maxPplDensity
- minPplDensity
- pplDensity
ErrorInfo:
type: object
required:
- status
- code
- message
properties:
status:
type: integer
description: HTTP status code returned along with this error response.
code:
type: string
description: Code given to this error.
message:
type: string
description: Detailed error description.
responses:
RetrieveLocationBadRequest400:
description: >-
Problem with the client request. In addition to generic scenarios of
`INVALID_ARGUMENT`, `INVALID_CREDENTIAL`, `INVALID_TOKEN`, another
scenarios may exist:
- The area is not a polygon shape or exceeds supported complexity ("code": "POPULATION_DENSITY_DATA.INVALID_AREA", "message": "The area is not a polygon shape or exceeds supported complexity")
- Indicated combination of area, time interval and precision is too big ("code": "POPULATION_DENSITY_DATA.UNSUPPPORTED_REQUEST", "message": "Indicated combination of area, time interval and precision is too big")
- Indicated `startDate` is greater than the maximum allowed ("code": "POPULATION_DENSITY_DATA.MAX_STARTDATE_EXCEEDED", "message": "Indicated startDate is greater than the maximum allowed")
- Indicated `startDate` is earlier than the minimum allowed ("code": "POPULATION_DENSITY_DATA.MIN_STARTDATE_EXCEEDED", "message": "Indicated startDate is earlier than the minimum allowed")
- Indicated `endDate` is earlier than the `startDate` ("code": "POPULATION_DENSITY_DATA.INVALID_END_DATE", "message": "Indicated endDate is earlier than the startDate")
- Indicated time period is greater than the maximum allowed (More than maximum hours between startDate and endDate) ("code": "POPULATION_DENSITY_DATA.MAX_TIME_PERIOD_EXCEEDED", "message": "Indicated time period is greater than the maximum allowed (More than maximum hours between startDate and endDate)")
- Indicated cell precision (Geohash level) is not supported ("code": "POPULATION_DENSITY_DATA.UNSUPPORTED_PRECISION", "message": "Indicated cell precision (Geohash level) is not supported")
- Indicated combination of area, time interval and precision is too big for a sync response ("code": "POPULATION_DENSITY_DATA.UNSUPPORTED_SYNC_RESPONSE", "message": "Indicated combination of area, time interval and precision is too big for a sync response")
headers:
x-correlator:
$ref: '#/components/headers/x-correlator'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorInfo'
examples:
InvalidArgument:
value:
status: 400
code: INVALID_ARGUMENT
message: Invalid input
GENERIC_400_INVALID_CREDENTIAL:
value:
status: 400
code: INVALID_CREDENTIAL
message: Only Access token is supported
GENERIC_400_INVALID_TOKEN:
value:
status: 400
code: INVALID_TOKEN
message: Only bearer token is supported
InvalidAreaIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.INVALID_AREA
message: The area is not a polygon shape or has an arbitrary complexity
UnsupportedRequestIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.UNSUPPPORTED_REQUEST
message: >-
Indicated combination of area, time interval and precision is
too big
MaxStartDateIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.MAX_STARTDATE_EXCEEDED
message: Indicated startDate is greater than the maximum allowed
MinStartDateIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.MIN_STARTDATE_EXCEEDED
message: Indicated startDate is earlier than the minimum allowed
InvalidEndDateIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.INVALID_END_DATE
message: Indicated endDate is earlier than the startDate
MaxDurationIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.MAX_TIME_PERIOD_EXCEEDED
message: >-
Indicated time period is greater than the maximum allowed
(More than maximum hours between startDate and endDate)
PrecisionNotSupportedIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.UNSUPPORTED_PRECISION
message: Indicated cell precision (Geohash length) is not supported
UnsupportedSyncResponseIssue:
value:
status: 400
code: POPULATION_DENSITY_DATA.UNSUPPORTED_SYNC_RESPONSE
message: >-
Indicated combination of area, time interval and precision is
too big for a sync response
Generic400:
description: Problem with the client request
headers:
x-correlator:
$ref: '#/components/headers/x-correlator'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorInfo'
example:
status: 400
code: INVALID_ARGUMENT
message: Client specified an invalid argument, request body or query param
Generic401:
description: Unauthorized
headers:
x-correlator:
$ref: '#/components/headers/x-correlator'
content:
app
# --- truncated at 32 KB (37 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/global-system-for-mobile-communications/refs/heads/main/openapi/population-density-api-openapi.yml