# Corona Tracker ## Overview 1. JSON Rest with Bearer token authorization 2. Validation errors returned with `422` status code (Dont run any retry logic for this status 4xx status codes) 3. API base `https://togetherwecan-api-00.arimac.digital/api` 4. The app uses 2 types for tokens. A short lived token issued when user authenticating, a long lived token with scope set to `encounters:submit` to submit encounters. **Sample error response** **Response** { "errors": [ "error 1", "error 2" ] } ## Common endpoints ### Login The JWT token include a custom claim called `scope` which includes user's token scope list in an _array_. Below scopes are currently utylized by the system - **profile** for users assigned when authenticated using sms otp method - **analyze** for admin users #### POST /auth/login **Request** { "email": "sahan@demo.com", "password": "sahan123", "scopes": ["analyze"], "captcha_response": "sdsdsd" } **Response** { "token": "<token>" } ## User endpoints ### Request a OTP Before a user is registered an OTP should be obtained #### POST /auth/otp **Request** { "phone": "772754541" } **Response** { "success": true } ### Register a user Provide a phone number and OTP code to register. If user is already registered system will update the existing record. #### POST /auth/register **Request** { "phone": "772754541", "code" : "1234" } **Response** { token_type": "Bearer", "expires_in": 1296000, "access_token": "...", "refresh_token": "..." } ### Get token from refresh token #### POST /auth/refresh_token **Request** { "refresh_token": "..." } **Response** { "token_type": "Bearer", "expires_in": 31536000, "access_token": "..." } ### Get user details #### GET /me `Authorization: Bearer <token>` **Response** { "phone": "772754541", "state": 1, "encoded_id": "QxomeWjBOLM8A5G", "secret": "$2y$10$SBXy823s5haIfV3ZmZmpZOo77JATz31Br4rzR6bcO4ZikBpmgCyua" } ### Update user #### POST /me `Authorization: Bearer <token>` **Request** { "state": 1 } **Response** { "success": true } ### Add/Update user's public key #### POST /me/public_key **Request** { "public_key": "..." } **Response** { "success": true } ### Get token for encounter submission #### GET /me/encounter_submission_token **Repose** { "token": "..." } ### Get public key for encryption #### GET /meta/public_key **Response** { "public_key": "..." } ### Get available health states #### GET /meta/health_states `Authorization: Bearer <token>` **Response** { "health_states": [ {"id": 1, "label_EN": "Normal"}, {"id": 1, "label_EN": "Under self quarantine"}, {"id": 1, "label_EN": "Tested - negative"}, {"id": 1, "label_EN": "Tested - positive"} ] } ### Submit data about encounters #### POST {endpoint} `Authorization: Bearer <token>` **Request** { "PartitionKey": "25ebdc72-7b96-4f47-9a55-1237f976cb86", "Data": [ { "exposed_by": 0, "time": 1585842872273, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-55" } ] }, { "exposed_by": 0, "time": 1585842890567, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-53" } ] }, { "exposed_by": 0, "time": 1585842844494, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-54" } ] }, { "exposed_by": 0, "time": 1585842994423, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-52" } ] }, { "exposed_by": 0, "time": 1585842679918, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-58" } ] }, { "exposed_by": 0, "time": 1585842634878, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-56" } ] }, { "exposed_by": 0, "time": 1585842949460, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-57" } ] }, { "exposed_by": 0, "time": 1585842799449, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-59" } ] }, { "exposed_by": 0, "time": 1585842754484, "exposedTo": [ { "user_id": "22BF6D0F0FD92CC0959D", "time": "26430553", "signature": "6096974128b5b1a1fefa51c1146663a418f61c59", "distance": "-58" } ] } ] } **Response** { "success": true } ### Check if app update is required #### POST /meta/app_update **Request** { "platfomr": "ios|android", "version": "1.0.0" } **Response** { "update_required": false } ### Submit support request #### POST me/support_requests { "name": "Sahan", "number": "772754541", "nic": "5454564", "address": "123 main st\ncolombo", "request": "Help!", "category": "Grocery" } ### Get support request quota #### GET me/support_requests/quota { "daily_submitted": 1, "limit_met": true, "remaining": 0 } ## Admin ### Query support requests Parameters - `status`: 1 = open, 0 = closed `?status=0`, by default all results are returned - `page`: paginating result `?page=1` - `limit`: default to 100 - `sort`: default to asc (asc|desc) #### GET /admin/support_requests **Response** { "data": [...], "total": "200" } ### Close a support request #### POST /admin/support_requests/{id}/close # Internal APIs ## Query users by encoded id #### POST /admin/users/query **Testing token** - bafc1dec2abfc3aa2eb326f8881c6f6a `Authorization: Bearer <token>` *Request* { "encoded_ids": [ "GNnrgKLday2Md8o", "GNnrgKLday2Md8o", "GNnrgKLday2Md8o", "GNnrgKLday2Md8o", "GNnrgKLday2Md8o", "GNnrgKLday2Md8o" ] } *Response* { "users": [ { "encoded_id": "GNnrgKLday2Md8o", "phone": "772729382", "state": "normal", "created_at": "" }, { "encoded_id": "GNnrgKLday2Md8o", "phone": "772729382", "state": "normal", "created_at": "" }, { "encoded_id": "GNnrgKLday2Md8o" //no user found } ] }