{ "swagger": "2.0", "basePath": "/api/v4", "produces": [ "application/json" ], "consumes": [ "application/json" ], "schemes": [ "https" ], "info": { "description": "# API specification for Simple Server\n## Sync APIs\nThis API spec documents the endpoints that the devices (that are offline to varying levels) will use to sync data. The sync end points will send and receive bulk (a list of) entities. Both sending and receiving can be batched with configurable batch-sizes to accommodate low network bandwidth situations.\n## Nesting resources\nThe APIs have been designed to provide an optimal balance between accuracy and simplicity. Some of the APIs (patients) will be nested, and some other (blood pressures) will be flat.\n## Authentication\nTODO\n\n## Sync Mechanism\nRefer to the [related ADR](https://github.com/simpledotorg/simple-server/blob/master/doc/arch/001-synchronization.md).\n", "version": "v4", "title": "Simple Server", "x-logo": { "url": "/assets/rtsl_logo-d7e4808e72f6d12641fd4a4f64669ed76d32170cd7a1e7fb9206ef7d1ba413c9.png", "backgroundColor": "#FFFFFF" }, "contact": { "email": "eng-backend@resolvetosavelives.org" }, "license": { "name": "MIT", "url": "https://github.com/simpledotorg/simple-server/blob/master/LICENSE" } }, "paths": { "/blood_sugars/sync": { "post": { "summary": "Syncs blood sugar data from device to server.", "tags": [ "Blood Sugar" ], "security": [ { "basic": [ ] } ], "parameters": [ { "name": "HTTP_X_USER_ID", "in": "header", "type": "uuid" }, { "name": "HTTP_X_FACILITY_ID", "in": "header", "type": "uuid" }, { "name": "blood_sugars", "in": "body", "schema": { "type": "object", "properties": { "blood_sugars": { "$ref": "#/definitions/blood_sugars" } }, "required": [ "blood_sugars" ] } } ], "responses": { "200": { "description": "some, or no errors were found", "schema": { "type": "object", "properties": { "errors": { "$ref": "#/definitions/errors" } } } }, "403": { "description": "user is not allowed to sync" } } }, "get": { "summary": "Syncs blood sugar data from server to device.", "tags": [ "Blood Sugar" ], "security": [ { "basic": [ ] } ], "parameters": [ { "name": "HTTP_X_USER_ID", "in": "header", "type": "uuid" }, { "name": "HTTP_X_FACILITY_ID", "in": "header", "type": "uuid" }, { "name": "process_token", "type": "string", "format": "byte", "description": "Token containing all the information needed to process batch requests from the user", "in": "query" }, { "in": "query", "name": "limit", "type": "integer", "description": "Number of record to retrieve (a.k.a batch-size)" } ], "responses": { "200": { "description": "blood sugar received", "schema": { "type": "object", "properties": { "blood_sugars": { "$ref": "#/definitions/blood_sugars" }, "process_token": { "$ref": "#/definitions/process_token" } }, "required": [ "blood_sugars", "process_token" ] } }, "403": { "description": "user is not allowed to sync" } } } }, "/patient/activate": { "post": { "summary": "Request an OTP to be sent to a patient", "tags": [ "Patient" ], "parameters": [ { "name": "request_body", "in": "body", "schema": { "type": "object", "properties": { "passport_id": { "$ref": "#/definitions/uuid" } } }, "description": "Patient's BP Passport UUID" } ], "responses": { "200": { "description": "Patient is found and an OTP is sent to their phone" }, "404": { "description": "Incorrect passport id" } } } }, "/patient/login": { "post": { "summary": "Log in a patient with BP Passport UUID and OTP", "tags": [ "Patient" ], "parameters": [ { "name": "request_body", "in": "body", "schema": { "type": "object", "properties": { "passport_id": { "$ref": "#/definitions/uuid" }, "otp": { "$ref": "#/definitions/non_empty_string" } } }, "description": "Patient's BP Passport UUID and OTP" } ], "responses": { "200": { "description": "Correct OTP is submitted and API credentials are returned", "schema": { "type": "object", "properties": { "patient": { "$ref": "#/definitions/login_patient" } } } }, "401": { "description": "Incorrect BP Passport UUID or OTP" } } } }, "/patient": { "get": { "summary": "Fetch patient information", "tags": [ "Patient" ], "security": [ { "basic": [ ] } ], "parameters": [ { "name": "HTTP_X_PATIENT_ID", "in": "header", "type": "uuid" } ], "responses": { "200": { "description": "Patient information is returned", "schema": { "type": "object", "properties": { "patient": { "$ref": "#/definitions/patient" } } } }, "401": { "description": "Invalid patient ID header" } } } }, "/users/find": { "post": { "summary": "Find a existing user", "tags": [ "User" ], "parameters": [ { "name": "phone_number", "in": "body", "schema": { "type": "object", "properties": { "phone_number": { "$ref": "#/definitions/non_empty_string" } }, "required": [ "phone_number" ] } } ], "responses": { "200": { "description": "user is found", "schema": { "type": "object", "properties": { "user": { "$ref": "#/definitions/find_user" } } } }, "404": { "description": "user is not found" } } } }, "/users/activate": { "post": { "summary": "Authenticate user, request OTP, and get user information", "tags": [ "User" ], "parameters": [ { "name": "user", "in": "body", "schema": { "type": "object", "properties": { "user": { "$ref": "#/definitions/activate_user" } }, "required": [ "user" ] } } ], "responses": { "200": { "description": "user otp is reset and new otp is sent as an sms", "schema": { "type": "object", "properties": { "user": { "$ref": "#/definitions/user" } }, "required": [ "user" ] } }, "401": { "description": "incorrect user id or password, authentication failed", "schema": { "type": "object", "properties": { "errors": { "type": "object", "properties": { "user": { "type": "array", "items": { "type": "string" }, "description": "List of descriptive error strings" } } } }, "required": [ "errors" ] } } } } }, "/users/me/": { "parameters": [ { "name": "HTTP_X_USER_ID", "in": "header", "type": "uuid", "required": true }, { "name": "HTTP_X_FACILITY_ID", "in": "header", "type": "uuid", "required": true } ], "get": { "summary": "Fetch user information", "tags": [ "User" ], "security": [ { "basic": [ ] } ], "responses": { "200": { "description": "returns user information", "schema": { "type": "object", "properties": { "user": { "$ref": "#/definitions/user" } }, "required": [ "user" ] } }, "401": { "description": "authentication failed" } } } } }, "definitions": { "error": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid", "description": "Id of the record with errors" }, "schema": { "type": "array", "items": { "type": "string" }, "description": "List of json schema error strings describing validation errors" }, "field_with_error": { "type": "array", "items": { "type": "string" } } } }, "errors": { "type": [ "null", "array" ], "items": { "$ref": "#/definitions/error" } }, "process_token": { "name": "process_token", "type": "string", "format": "byte", "description": "Token containing all the information needed to process batch requests from the user" }, "timestamp": { "type": "string", "format": "date-time", "description": "Timestamp with millisecond precision." }, "uuid": { "type": "string", "format": "uuid", "pattern": "[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}" }, "non_empty_string": { "type": "string", "minLength": 1, "description": "This string should not be empty." }, "nullable_timestamp": { "type": [ "string", "null" ], "format": "date-time", "description": "Timestamp with millisecond precision." }, "bcrypt_password": { "type": "string", "pattern": "^\\$[0-9a-z]{2}\\$[0-9]{2}\\$[A-Za-z0-9\\.\\/]{53}$", "description": "Bcrypt password digest" }, "blood_sugar": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "blood_sugar_type": { "type": "string", "enum": [ "random", "post_prandial", "fasting", "hba1c" ] }, "blood_sugar_value": { "type": "number" }, "deleted_at": { "$ref": "#/definitions/nullable_timestamp" }, "created_at": { "$ref": "#/definitions/timestamp" }, "updated_at": { "$ref": "#/definitions/timestamp" }, "recorded_at": { "$ref": "#/definitions/timestamp" }, "patient_id": { "$ref": "#/definitions/uuid" }, "facility_id": { "$ref": "#/definitions/uuid" }, "user_id": { "$ref": "#/definitions/uuid" } }, "required": [ "id", "blood_sugar_type", "blood_sugar_value", "created_at", "updated_at", "patient_id", "facility_id", "user_id" ] }, "blood_sugars": { "type": [ "null", "array" ], "items": { "$ref": "#/definitions/blood_sugar" } }, "login_patient": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "access_token": { "$ref": "#/definitions/non_empty_string" }, "passport": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "shortcode": { "$ref": "#/definitions/non_empty_string" } } } } }, "patient": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "full_name": { "$ref": "#/definitions/non_empty_string" }, "age": { "type": [ "integer", "null" ] }, "gender": { "type": "string", "enum": [ "male", "female", "transgender" ] }, "status": { "type": "string", "enum": [ "active", "dead", "migrated", "unresponsive", "inactive" ] }, "recorded_at": { "$ref": "#/definitions/timestamp" }, "reminder_consent": { "type": "string", "enum": [ "granted", "denied" ] }, "phone_numbers": { "type": [ "null", "array" ], "items": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "number": { "$ref": "#/definitions/non_empty_string" } } } }, "address": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "street_address": { "type": [ "string", "null" ] }, "village_or_colony": { "type": [ "string", "null" ] }, "district": { "type": [ "string", "null" ] }, "zone": { "type": [ "string", "null" ] }, "state": { "type": [ "string", "null" ] }, "country": { "type": [ "string", "null" ] }, "pin": { "type": [ "string", "null" ] } } }, "registration_facility": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "name": { "$ref": "#/definitions/non_empty_string" }, "street_address": { "type": [ "string", "null" ] }, "village_or_colony": { "type": [ "string", "null" ] }, "district": { "type": [ "string", "null" ] }, "state": { "type": [ "string", "null" ] }, "country": { "type": [ "string", "null" ] }, "pin": { "type": [ "string", "null" ] } } }, "medical_history": { "type": "object", "properties": { "chronic_kidney_disease": { "type": "string", "enum": [ "yes", "no", "unknown" ] }, "diabetes": { "type": "string", "enum": [ "yes", "no", "unknown" ] }, "hypertension": { "type": "string", "enum": [ "yes", "no", "unknown" ] }, "prior_heart_attack": { "type": "string", "enum": [ "yes", "no", "unknown" ] }, "prior_stroke": { "type": "string", "enum": [ "yes", "no", "unknown" ] } } }, "blood_pressures": { "type": [ "null", "array" ], "items": { "type": "object", "properties": { "systolic": { "type": "integer" }, "diastolic": { "type": "integer" }, "recorded_at": { "$ref": "#/definitions/timestamp" }, "facility": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "name": { "$ref": "#/definitions/non_empty_string" }, "street_address": { "type": [ "string", "null" ] }, "village_or_colony": { "type": [ "string", "null" ] }, "district": { "type": [ "string", "null" ] }, "state": { "type": [ "string", "null" ] }, "country": { "type": [ "string", "null" ] }, "pin": { "type": [ "string", "null" ] } } } } } }, "blood_sugars": { "type": [ "null", "array" ], "items": { "type": "object", "properties": { "blood_sugar_value": { "type": "number" }, "blood_sugar_type": { "type": "string", "enum": [ "random", "post_prandial", "fasting", "hba1c" ] }, "recorded_at": { "$ref": "#/definitions/timestamp" }, "facility": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "name": { "$ref": "#/definitions/non_empty_string" }, "street_address": { "type": [ "string", "null" ] }, "village_or_colony": { "type": [ "string", "null" ] }, "district": { "type": [ "string", "null" ] }, "state": { "type": [ "string", "null" ] }, "country": { "type": [ "string", "null" ] }, "pin": { "type": [ "string", "null" ] } } } } } }, "appointments": { "type": [ "null", "array" ], "items": { "type": "object", "properties": { "scheduled_date": { "type": "string", "format": "date" }, "status": { "type": "string", "enum": [ "scheduled", "cancelled", "visited" ] }, "facility": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "name": { "$ref": "#/definitions/non_empty_string" }, "street_address": { "type": [ "string", "null" ] }, "village_or_colony": { "type": [ "string", "null" ] }, "district": { "type": [ "string", "null" ] }, "state": { "type": [ "string", "null" ] }, "country": { "type": [ "string", "null" ] }, "pin": { "type": [ "string", "null" ] } } } } } }, "medications": { "type": [ "null", "array" ], "items": { "type": "object", "properties": { "name": { "$ref": "#/definitions/non_empty_string" }, "dosage": { "type": "string" }, "rxnorm_code": { "type": "string" }, "is_protocol_drug": { "type": "boolean" } } } } } }, "user": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "deleted_at": { "$ref": "#/definitions/nullable_timestamp" }, "created_at": { "$ref": "#/definitions/timestamp" }, "updated_at": { "$ref": "#/definitions/timestamp" }, "full_name": { "$ref": "#/definitions/non_empty_string" }, "phone_number": { "$ref": "#/definitions/non_empty_string" }, "password_digest": { "$ref": "#/definitions/bcrypt_password" }, "registration_facility_id": { "$ref": "#/definitions/uuid" }, "sync_approval_status": { "type": [ "string", "null" ] }, "sync_approval_status_reason": { "type": [ "string", "null" ] } }, "required": [ "id", "created_at", "updated_at", "full_name", "phone_number", "password_digest", "registration_facility_id" ] }, "find_user": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "sync_approval_status": { "type": [ "string", "null" ] } }, "required": [ "id" ] }, "activate_user": { "type": "object", "properties": { "id": { "$ref": "#/definitions/uuid" }, "password": { "$ref": "#/definitions/non_empty_string" } }, "required": [ "id", "password" ] } }, "securityDefinitions": { "basic": { "type": "basic" } } }