forked from immuni-app/immuni-documentation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
API.yaml
366 lines (366 loc) · 13 KB
/
API.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
swagger: "2.0"
info:
version: "1.0.0"
title: "Immuni API"
basePath: "/v1"
tags:
- name: "App Configuration"
description: "The App can be partially customised through the Configuration Settings downloaded at the App startup and updated every time the App starts a session, whether in the foreground or background. For example, these include information such as the weights to be used by the Mobile Client in the calculation of the Total Risk Score."
- name: "OTP"
description: "The OTP Service provides an API to the National Healthcare Service for authorising OTPs that can be used to upload data from the Mobile Client via the Exposure Ingestion Service. The OTP is generated by the App and communicated by the user to the Healthcare Operator (e.g., during a phone call). The Healthcare Operator inserts the OTP into the HIS, which then registers the OTP on the OTP Service. The OTP automatically expires after a defined interval. If the data have not been uploaded by the time the OTP expires, the user will have to restart the process with a new OTP."
- name: "Exposure Ingestion"
description: "The Exposure Ingestion Service provides an API for the Mobile Client to upload its TEKs for the previous 14 days, in the case that the user tests positive for SARS-CoV-2 and decides to share them. Contextually, the Mobile Client uploads the Epidemiological Infos from the previous 14 days, if any. If some Epidemiological Infos are indeed uploaded, the user's Province of Domicile is uploaded too. The upload can only take place with an authorised OTP. The Exposure Ingestion Service is also responsible for periodically generating the TEK Chunks to be published by the Exposure Reporting Service. The TEK Chunks are assigned a unique incremental index and are immutable. They are generated periodically as the Mobile Clients upload new TEKs. TEK Chunks older than 14 days are automatically deleted from the database by an async cleanup job. Province of Domicile and Epidemiological Infos are forwarded to the Analytics Service."
- name: "Exposure Reporting"
description: "The Exposure Reporting Service makes the TEK Chunks created by the Exposure Ingestion Service available to the Mobile Client. Only TEK Chunks for the last 14 days are made available. To avoid downloading the same TEKs multiple times, the Mobile Clients fetch the indexes of the TEK Chunks available to download first. Then, they only actually download TEK Chunks with indexes for which TEK Chunks have not been downloaded before."
schemes:
- "https"
paths:
/settings:
get:
tags:
- "App Configuration"
summary: "The Mobile Client fetches the Configuration Settings. Different Configuration Settings may be made available for different platforms (i.e., iOS and Android) and App build numbers."
produces:
- "application/json"
parameters:
- name: "platform"
in: "query"
description: "The Mobile Client's platform."
required: true
type: "string"
enum:
- "ios"
- "android"
- name: "build"
in: "query"
description: "The App's build number."
required: true
type: "integer"
minimum: 1
format: "int32"
responses:
200:
description: "A JSON-formatted dictionary. Specifications are being worked out."
headers:
Cache-Control:
type: "string"
description: "Directives for caching the response. The Configuration Settings are cached for 60 minutes."
400:
description: "Invalid request."
/otp:
post:
tags:
- "OTP"
summary: "The provided OTP authorises the upload of the Mobile Client's TEKs. This API will not be publicly exposed, to prevent unauthorised users from reaching it. Authentication for having the OTP Service and the HIS trust each other is configured at the infrastructure level. The payload also contains the start date of the symptoms, so that the Exposure Ingestion Service can compute the Transmission Risk for each uploaded TEK."
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "body"
description: "A JSON-formatted dictionary containing the OTP and the start date of the symptoms."
required: true
schema:
$ref: "#/definitions/OTPUpload"
responses:
204:
description: "Operation completed successfully."
400:
description: "Invalid data. An APIError is returned. Possible error codes are 1400 (\"Unexpected empty body\") and 1401 (\"Body not compliant with the defined schema\")."
schema:
$ref: "#/definitions/APIError"
/ingestion/check-otp:
post:
tags:
- "Exposure Ingestion"
summary: "The Mobile Client validates the OTP prior to uploading data. The request is authenticated with the OTP to be validated. Using the dedicated request header, the Mobile Client can indicate to the server that the call it is making is a dummy one. The server will ignore the content of such calls."
consumes:
- "application/json; charset=utf-8"
produces:
- "application/json"
parameters:
- in: "header"
name: "Immuni-Dummy-Data"
type: "integer"
required: true
minimum: 0
maximum: 1
- in: "body"
name: "body"
description: "A JSON-formatted dictionary containing a padding field to emulate the upload request payload size."
required: true
schema:
$ref: "#/definitions/CheckOTP"
responses:
204:
description: "Operation completed successfully."
400:
description: "Invalid data. An APIError is returned. The only possible error code is 1100 (\"Missing required input parameters\")."
schema:
$ref: "#/definitions/APIError"
401:
description: "Unauthorised request: invalid OTP."
security:
- otp_bearer: []
/ingestion/upload:
post:
tags:
- "Exposure Ingestion"
summary: "Once it has validated the OTP, the Mobile Client uploads its TEKs for the past 14 days, together with the user’s Province of Domicile. If any Epidemiological Infos from the previous 14 days are available, the Mobile Client uploads those too. The timestamp that accompanies each TEK is referred to the Mobile Client’s system time. For this reason, the Mobile Client informs the Exposure Ingestion Service about its system time so that a skew can be corrected. Using the dedicated request header, the Mobile Client can indicate to the server that the call it is making is a dummy one. The server will ignore the content of such calls."
consumes:
- "application/json; charset=utf-8"
produces:
- "application/json"
parameters:
- in: "header"
name: "Immuni-Client-Clock"
type: "integer"
format: "int32"
required: true
- in: "header"
name: "Immuni-Dummy-Data"
type: "integer"
minimum: 0
maximum: 1
required: true
- in: "body"
name: "body"
description: "A JSON-formatted dictionary containing the data to upload. The server will ignore transmission_risk_level, which is to be overridden as a result of server-side computations."
required: true
schema:
$ref: "#/definitions/Upload"
responses:
204:
description: "Operation completed successfully."
400:
description: "Invalid data. An APIError is returned. The only possible error code is 1100 (\"Missing required input parameters\")."
schema:
$ref: "#/definitions/APIError"
401:
description: "Unauthorised request: invalid OTP."
security:
- otp_bearer: []
/keys/index:
get:
tags:
- "Exposure Reporting"
summary: "Return the index of the oldest relevant TEK Chunk (no older than 14 days) and the index of the newest available TEK Chunk. It is up to the Mobile Client not to download the same TEK Chunk more than once."
produces:
- "application/json"
responses:
200:
description: "Operation completed successfully."
schema:
$ref: "#/definitions/TEKChunkIndexes"
headers:
Cache-Control:
type: "string"
description: "Directives for caching the response. The indexes are cached for 30 minutes."
404:
description: "No TEK Chunks found."
/keys/{TEKChunkIndex}:
get:
tags:
- "Exposure Reporting"
summary: "Given a specific TEK Chunk index, the Mobile Client downloads the associated TEK Chunk from the Exposure Reporting Service."
produces:
- "application/zip"
parameters:
- name: "TEKChunkIndex"
in: "path"
description: "The TEK Chunk's incremental number."
required: true
minimum: 1
type: "integer"
format: "int32"
responses:
200:
description: "Operation completed successfully."
headers:
Cache-Control:
type: "string"
description: "Directives for caching the response. TEK Chunks are cached for 15 days."
404:
description: "TEK Chunk not found."
securityDefinitions:
otp_bearer:
type: "apiKey"
name: "Authorization"
in: "header"
definitions:
OTPUpload:
type: "object"
required:
- "otp"
- "symptoms_started_on"
properties:
otp:
type: "string"
pattern: "^[AEFHIJKLQRSUWXYZ1-9]{10}$"
example: "9K2RAY8UUQ"
symptoms_started_on:
type: "string"
format: "date"
Upload:
type: "object"
properties:
teks:
type: "array"
maxItems: 14
items:
$ref: "#/definitions/TEK"
province:
type: "string"
pattern: "^[A-Z]{2}$"
example: "MB"
padding:
type: "string"
pattern: "^[a-zA-Z0-9]*$"
exposure_detection_summaries:
type: "array"
items:
$ref: "#/definitions/ExposureDetectionSummary"
TEK:
type: "object"
required:
- "key_data"
- "rolling_start_number"
- "rolling_period"
properties:
key_data:
type: "string"
example: "utdH33iMRTapATp7iK3hdA=="
rolling_start_number:
type: "integer"
format: "int32"
minimum: 0
example: 2648160
rolling_period:
type: "integer"
format: "int32"
minimum: 0
example: 144
TEKChunkIndexes:
type: "object"
required:
- "oldest"
- "newest"
properties:
oldest:
type: "integer"
minimum: 1
example: 1
newest:
type: "integer"
minimum: 1
example: 14
ExposureDetectionSummary:
type: "object"
required:
- "date"
- "matched_key_count"
- "days_since_last_exposure"
- "attenuation_durations"
- "maximum_risk_score"
properties:
date:
type: "string"
format: "date"
matched_key_count:
type: "integer"
format: "int32"
minimum: 1
example: 2
days_since_last_exposure:
type: "integer"
format: "int32"
maximum: 14
example: 1
attenuation_durations:
type: "array"
minItems: 3
maxItems: 3
example: [300, 0, 0]
items:
type: "integer"
format: "int32"
minimum: 0
maximum_risk_score:
type: "integer"
minimum: 0
maximum: 4096
example: 4
exposure_info:
type: "array"
items:
$ref: "#/definitions/ExposureInfo"
CheckOTP:
type: "object"
required:
- "padding"
properties:
padding:
type: "string"
pattern: "^[a-zA-Z0-9]*$"
ExposureInfo:
type: "object"
required:
- "date"
- "duration"
- "attenuation_value"
- "attenuation_durations"
- "transmission_risk_level"
- "total_risk_score"
properties:
date:
type: "string"
format: "date"
duration:
type: "integer"
format: "int32"
maximum: 1800
minimum: 0
example: 5
attenuation_value:
type: "integer"
format: "int32"
minimum: 0
maximum: 255
example: 45
attenuation_durations:
type: "array"
minItems: 3
maxItems: 3
example: [300, 0, 0]
items:
type: "integer"
format: "int32"
minimum: 0
transmission_risk_level:
type: "integer"
format: "int32"
minimum: 0
maximum: 8
example: 1
total_risk_score:
type: "integer"
format: "int32"
minimum: 0
maximum: 4096
example: 4
APIError:
type: "object"
required:
- "error_code"
- "message"
properties:
error_code:
type: "integer"
minimum: 0
format: "int32"
example: 1400
message:
type: "string"
pattern: "^[A-Za-z0-9 ]{1,64}$"
example: "Unexpected empty body."