{
  "openapi": "3.0.0",
  "info": {
    "title": "Blob API",
    "version": "1.0",
    "description": "The Tidepool API is an HTTP REST API used by Tidepool clients use to communicate with the Tidepool Platform.\n\nFor more information, see the [Getting Started](../docs/quick-start.md) section.",
    "termsOfService": "https://developer.tidepool.org/terms-of-use",
    "contact": {
      "name": "Tidepool",
      "url": "https://www.tidepool.org/",
      "email": "support@tidepool.org"
    },
    "license": {
      "name": "BSD-2-Clause",
      "url": "https://github.com/tidepool-org/platform/blob/master/LICENSE"
    },
    "x-tidepool-service": "https://github.com/tidepool-org/platform/blob"
  },
  "servers": [
    {
      "url": "https://external.integration.tidepool.org",
      "description": "integration"
    },
    {
      "url": "https://api.tidepool.org",
      "description": "production"
    },
    {
      "url": "https://dev1.dev.tidepool.org",
      "description": "dev1"
    },
    {
      "url": "https://qa1.development.tidepool.org",
      "description": "qa1"
    },
    {
      "url": "https://qa2.development.tidepool.org",
      "description": "qa2"
    }
  ],
  "security": [
    {
      "sessionToken": []
    }
  ],
  "tags": [
    {
      "name": "Internal",
      "description": "APIs intended for internal use by Tidepool."
    },
    {
      "name": "Blobs",
      "description": "\nList, create, and manage binary blobs.\nThe content format may be anything, because the blobs are treated as opaque data by the service. Each blob has a `status`. If a blob is created without content, then its status is `created`. If the blob is created with content or has been updated to include content then its status is `available`."
    },
    {
      "name": "Device Logs",
      "description": "Create and list device logs."
    }
  ],
  "paths": {
    "/v1/users/{userId}/device_logs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/tidepooluserid"
        }
      ],
      "post": {
        "operationId": "UploadDeviceLogs",
        "summary": "Upload new device logs as json",
        "description": "Uploads a new device logs json to the user's account. The `Digest` header must represent the MD5 hash of the json data content.",
        "parameters": [
          {
            "$ref": "#/components/parameters/digestmd5.v1"
          },
          {
            "$ref": "#/components/parameters/logs-start-at.v1"
          },
          {
            "$ref": "#/components/parameters/logs-end-at.v1"
          }
        ],
        "requestBody": {
          "description": "array of JSON data",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/device-log-content.v1"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/DeviceLogsMetadata"
          },
          "400": {
            "$ref": "#/components/responses/badrequest.v1"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized.v1"
          },
          "403": {
            "$ref": "#/components/responses/forbidden.v1"
          },
          "404": {
            "$ref": "#/components/responses/notfound.v1"
          }
        },
        "tags": [
          "Device Logs"
        ]
      },
      "get": {
        "operationId": "ListDeviceLogs",
        "summary": "List device logs metadata",
        "description": "List previously uploaded device logs json data in the user's account. The list must be filtered with startAt and endAt parameters",
        "parameters": [
          {
            "$ref": "#/components/parameters/start-at.v1"
          },
          {
            "$ref": "#/components/parameters/end-at.v1"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/DeviceLogsMetadataList"
          },
          "400": {
            "$ref": "#/components/responses/badrequest.v1"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized.v1"
          },
          "403": {
            "$ref": "#/components/responses/forbidden.v1"
          },
          "404": {
            "$ref": "#/components/responses/notfound.v1"
          }
        },
        "tags": [
          "Device Logs"
        ]
      }
    },
    "/v1/users/{userId}/blobs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/tidepooluserid"
        }
      ],
      "get": {
        "operationId": "ListBlobs",
        "summary": "List Binary Blobs",
        "description": "List previously uploaded binary blobs in the user's account. The list can be filtered with `mediaType` and `status` query parameters.",
        "parameters": [
          {
            "$ref": "#/components/parameters/mediatype.v1"
          },
          {
            "$ref": "#/components/parameters/status.v1"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/BlobMetadataList"
          }
        },
        "tags": [
          "Blobs"
        ]
      },
      "post": {
        "operationId": "CreateBlob",
        "summary": "Create New Binary Blob",
        "description": "Creates a new binary blob in the user's account. The `Content-Type` and the `Digest` headers must represent the media type and MD5 hash of the binary blob content, respectively.",
        "parameters": [
          {
            "$ref": "#/components/parameters/contenttype.v1"
          },
          {
            "$ref": "#/components/parameters/digestmd5.v1"
          }
        ],
        "requestBody": {
          "description": "Binary blob",
          "required": true,
          "content": {
            "*/*": {
              "schema": {
                "$ref": "#/components/schemas/content.v1"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/BlobMetadata"
          }
        },
        "tags": [
          "Blobs"
        ]
      },
      "delete": {
        "operationId": "DeleteAllBlobs",
        "summary": "Delete All Binary Blobs",
        "description": "Deletes all previously uploaded binary blobs in the user's account.",
        "responses": {
          "204": {
            "$ref": "#/components/responses/nocontent.v1"
          }
        },
        "tags": [
          "Blobs"
        ]
      }
    },
    "/v1/blobs/{blobId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/id.v1"
        }
      ],
      "get": {
        "operationId": "GetBlobMetadata",
        "summary": "Get Binary Blob Metadata",
        "description": "Get a previously uploaded binary blob in the user's account.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/BlobMetadata"
          }
        },
        "tags": [
          "Blobs"
        ]
      },
      "delete": {
        "operationId": "DeleteBlob",
        "summary": "Delete Binary Blob",
        "description": "Deletes a previously uploaded binary blob in the user's account. This operation fails if the `blobId` does not match the ID of an existing blob.",
        "responses": {
          "204": {
            "$ref": "#/components/responses/nocontent.v1"
          }
        },
        "tags": [
          "Blobs"
        ]
      }
    },
    "/v1/blobs/{blobId}/content": {
      "parameters": [
        {
          "$ref": "#/components/parameters/id.v1"
        }
      ],
      "get": {
        "operationId": "GetBlobContent",
        "summary": "Get Binary Blob Content",
        "description": "Retrieves the content of a binary blob in the user's account.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/BlobContent"
          }
        },
        "tags": [
          "Blobs"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "sessionToken": {
        "description": "Tidepool Session Token",
        "type": "apiKey",
        "name": "X-Tidepool-Session-Token",
        "in": "header"
      }
    },
    "responses": {
      "BlobMetadataList": {
        "description": "List of binary blob metadata",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/metadatalist.v1"
            }
          }
        }
      },
      "BlobMetadata": {
        "description": "Binary blob metadata",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/metadata.v1"
            }
          }
        },
        "links": {
          "DeleteBlob": {
            "operationId": "DeleteBlob",
            "parameters": {
              "blobId": "$response.body#/id"
            }
          },
          "GetBlobMetadata": {
            "operationId": "GetBlobMetadata",
            "parameters": {
              "blobId": "$response.body#/id"
            }
          },
          "GetBlobContent": {
            "operationId": "GetBlobContent",
            "parameters": {
              "blobId": "$response.body#/id"
            }
          }
        }
      },
      "BlobContent": {
        "description": "Binary blob content",
        "headers": {
          "Digest": {
            "$ref": "#/components/headers/digestmd5.v1"
          }
        },
        "content": {
          "*/*": {
            "schema": {
              "$ref": "#/components/schemas/content.v1"
            }
          }
        }
      },
      "DeviceLogsMetadata": {
        "description": "Device logs metadata",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/device-logs-metadata.v1"
            }
          }
        }
      },
      "DeviceLogsMetadataList": {
        "description": "List of device logs metadata",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/device-logs-metadatalist.v1"
            }
          }
        }
      },
      "badrequest.v1": {
        "description": "400 Bad Request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/error.v1"
            }
          }
        }
      },
      "unauthorized.v1": {
        "description": "401 Unauthorized",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/error.v1"
            }
          }
        }
      },
      "forbidden.v1": {
        "description": "403 Forbidden",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/error.v1"
            }
          }
        }
      },
      "notfound.v1": {
        "description": "404 Not Found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/error.v1"
            }
          }
        }
      },
      "nocontent.v1": {
        "description": "204 No Content"
      }
    },
    "schemas": {
      "tidepooluserid": {
        "type": "string",
        "title": "Tidepool User ID",
        "pattern": "^([0-9a-f]{10}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$",
        "description": "String representation of a Tidepool User ID. Old style IDs are 10-digit strings consisting of only hexadeximcal digits. New style IDs are 36-digit [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))",
        "readOnly": true,
        "x-go-type": "string"
      },
      "datetime.v1": {
        "title": "Date/Time",
        "description": "[RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) / [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) timestamp _with_ timezone information",
        "type": "string",
        "format": "date-time",
        "example": "2017-02-06T02:37:46Z",
        "x-go-type": "string"
      },
      "blob-id.v1": {
        "title": "Blob ID",
        "description": "Blob ID",
        "type": "string",
        "pattern": "^[0-9a-z]{32}$",
        "readOnly": true,
        "example": "97a9fae8a19b4da58bb48dc90c9562c9"
      },
      "digestmd5.v1": {
        "title": "MD5 Digest",
        "description": "MD5 digest of the content per [RFC 1321](https://www.ietf.org/rfc/rfc1321.txt), encoded as base64 ([RFC 4648](https://www.ietf.org/rfc/rfc4648.txt)).",
        "type": "string",
        "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
        "minLength": 24,
        "maxLength": 24,
        "example": "HUXZLQLMuI/KZ5KDcJPcOA==",
        "x-go-type": "string"
      },
      "size.v1": {
        "title": "Blob Size",
        "description": "Size of the binary blob, in bytes",
        "type": "integer",
        "format": "int64",
        "readOnly": true,
        "example": 1024
      },
      "device-logs-metadata.v1": {
        "title": "Device logs json metadata",
        "type": "object",
        "readOnly": true,
        "properties": {
          "id": {
            "$ref": "#/components/schemas/blob-id.v1"
          },
          "userId": {
            "$ref": "#/components/schemas/tidepooluserid"
          },
          "digestMD5": {
            "$ref": "#/components/schemas/digestmd5.v1"
          },
          "mediaType": {
            "type": "string",
            "enum": [
              "application/json"
            ]
          },
          "size": {
            "$ref": "#/components/schemas/size.v1"
          },
          "createdTime": {
            "$ref": "#/components/schemas/datetime.v1"
          },
          "startAtTime": {
            "$ref": "#/components/schemas/datetime.v1"
          },
          "endAtTime": {
            "$ref": "#/components/schemas/datetime.v1"
          }
        },
        "required": [
          "id",
          "userId",
          "digestMD5",
          "mediaType",
          "size",
          "createdTime",
          "startAtTime",
          "endAtTime"
        ],
        "example": {
          "id": "97a9fae8a19b4da58bb48dc90c9562c9",
          "userId": "4d94a5fb-642e-48f1-89b9-c6a3e6145342",
          "digestMD5": "HUXZLQLMuI/KZ5KDcJPcOA==",
          "mediaType": "application/json",
          "size": 1024,
          "createdTime": "2017-02-06T02:35:46Z",
          "startAtTime": "2017-02-06T02:35:46Z",
          "endAtTime": "2017-02-06T02:36:46Z"
        }
      },
      "device-logs-metadatalist.v1": {
        "title": "Device logs json list",
        "type": "array",
        "readOnly": true,
        "minItems": 0,
        "items": {
          "$ref": "#/components/schemas/device-logs-metadata.v1"
        },
        "example": [
          {
            "id": "97a9fae8a19b4da58bb48dc90c9562c9",
            "userId": "4d94a5fb-642e-48f1-89b9-c6a3e6145342",
            "digestMD5": "HUXZLQLMuI/KZ5KDcJPcOA==",
            "mediaType": "application/json",
            "size": 1024,
            "createdTime": "2017-02-06T02:35:46Z",
            "startAtTime": "2017-02-06T02:35:46Z",
            "endAtTime": "2017-02-06T02:36:46Z"
          }
        ]
      },
      "error.v1": {
        "title": "Error",
        "type": "object",
        "properties": {
          "code": {
            "type": "integer",
            "example": 404
          },
          "message": {
            "type": "string",
            "example": "Requested resources was not found"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "devicemodelname.v1": {
        "title": "Device Model Name",
        "description": "A string identifying the model of the device.\n\nThe `deviceModel` is a non-empty string that encodes the model of device.\nWe endeavor to match each manufacturer's standard for how they represent model name in terms of casing, whether parts of the name are represented as one word or two, etc.",
        "type": "string",
        "minLength": 1,
        "example": "Devicey McDeviceface",
        "x-tags": [
          "Data"
        ]
      },
      "deviceid.v1": {
        "title": "Device ID",
        "description": "Globally unique to device and repeatable with each upload, e.g. device make and model with serial number",
        "type": "string",
        "minLength": 1,
        "example": "MMT-1711:12345678",
        "x-tags": [
          "Data"
        ]
      },
      "device-log-content.v1": {
        "title": "Device log content",
        "description": "Device log entry.",
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "send",
              "receive",
              "error",
              "delegate",
              "delegateResponse",
              "connection"
            ]
          },
          "managerIdentifier": {
            "$ref": "#/components/schemas/devicemodelname.v1"
          },
          "deviceIdentifier": {
            "$ref": "#/components/schemas/deviceid.v1"
          },
          "timestamp": {
            "$ref": "#/components/schemas/datetime.v1"
          },
          "message": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "type",
          "managerIdentifier",
          "deviceIdentifier",
          "timestamp",
          "message"
        ],
        "example": {
          "type": "send",
          "managerIdentifier": "Devicey McDeviceface",
          "deviceIdentifier": "MMT-1711:12345678",
          "timestamp": "2017-02-06T02:37:46Z",
          "message": "sent something ..."
        }
      },
      "mediatype.v1": {
        "title": "MediaType",
        "description": "Media type as defined in [RFC 2045](https://www.ietf.org/rfc/rfc2045.txt).",
        "type": "string",
        "pattern": "^\\w+/[-+.\\w]+(;.+)?$",
        "example": "application/octet-stream"
      },
      "status.v1": {
        "title": "Blob status",
        "description": "Blob status",
        "type": "string",
        "enum": [
          "created",
          "available"
        ],
        "readOnly": true,
        "example": "created"
      },
      "revision.v1": {
        "title": "Blob Revision",
        "description": "Revision number of the blob",
        "type": "integer",
        "format": "int32",
        "minimum": 0,
        "example": 42
      },
      "metadata.v1": {
        "title": "Blob metadata",
        "type": "object",
        "readOnly": true,
        "properties": {
          "id": {
            "$ref": "#/components/schemas/blob-id.v1"
          },
          "userId": {
            "$ref": "#/components/schemas/tidepooluserid"
          },
          "digestMD5": {
            "$ref": "#/components/schemas/digestmd5.v1"
          },
          "mediaType": {
            "$ref": "#/components/schemas/mediatype.v1"
          },
          "size": {
            "$ref": "#/components/schemas/size.v1"
          },
          "status": {
            "$ref": "#/components/schemas/status.v1"
          },
          "createdTime": {
            "$ref": "#/components/schemas/datetime.v1"
          },
          "modifiedTime": {
            "$ref": "#/components/schemas/datetime.v1"
          },
          "deletedTime": {
            "$ref": "#/components/schemas/datetime.v1"
          },
          "revision": {
            "$ref": "#/components/schemas/revision.v1"
          }
        },
        "required": [
          "id",
          "userId",
          "digestMD5",
          "mediaType",
          "size",
          "status",
          "createdTime",
          "revision"
        ]
      },
      "metadatalist.v1": {
        "title": "Blob list",
        "type": "array",
        "readOnly": true,
        "minItems": 0,
        "items": {
          "$ref": "#/components/schemas/metadata.v1"
        }
      },
      "content.v1": {
        "title": "Blob content",
        "description": "Binary data.",
        "type": "string",
        "format": "binary",
        "readOnly": true
      }
    },
    "parameters": {
      "tidepooluserid": {
        "description": "Tidepool User ID",
        "name": "userId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/tidepooluserid"
        }
      },
      "start-at.v1": {
        "description": "Start At Datetime",
        "name": "startAtTime",
        "in": "query",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/datetime.v1"
        }
      },
      "end-at.v1": {
        "description": "End At Datetime",
        "name": "endAtTime",
        "in": "query",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/datetime.v1"
        }
      },
      "digestmd5.v1": {
        "description": "Base64-encoded MD5 hash of the resource, per [RFC 3230](https://www.ietf.org/rfc/rfc3230.txt)",
        "name": "Digest",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^md5=(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
          "minLength": 28,
          "maxLength": 28
        },
        "example": "md5=HUXZLQLMuI/KZ5KDcJPcOA=="
      },
      "logs-start-at.v1": {
        "description": "Starting time of device logs inside the uploaded json log",
        "name": "X-Logs-Start-At-Time",
        "in": "header",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/datetime.v1"
        }
      },
      "logs-end-at.v1": {
        "description": "End time of device logs inside the uploaded json log",
        "name": "X-Logs-End-At-Time",
        "in": "header",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/datetime.v1"
        }
      },
      "mediatype.v1": {
        "description": "Blob Media Type",
        "name": "mediaType",
        "in": "query",
        "required": false,
        "schema": {
          "$ref": "#/components/schemas/mediatype.v1"
        }
      },
      "status.v1": {
        "description": "Blob Status",
        "name": "status",
        "in": "query",
        "required": false,
        "schema": {
          "$ref": "#/components/schemas/status.v1"
        }
      },
      "contenttype.v1": {
        "description": "Content type of the resource",
        "name": "Content-Type",
        "in": "header",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/mediatype.v1"
        },
        "examples": {
          "binary": {
            "value": "application/octet-stream"
          },
          "text": {
            "value": "text/plain"
          },
          "text UTF-8": {
            "value": "text/plain; charset=utf-8"
          },
          "HTML": {
            "value": "text/html"
          },
          "JSON": {
            "value": "application/json"
          },
          "XML": {
            "value": "application/xml"
          },
          "XML text": {
            "value": "text/xml"
          },
          "JPEG image": {
            "value": "image/jpeg"
          },
          "PNG image": {
            "value": "image/png"
          },
          "MPEG4 video": {
            "value": "video/mp4"
          },
          "PDF": {
            "value": "application/pdf"
          },
          "ZIP": {
            "value": "application/zip"
          }
        }
      },
      "id.v1": {
        "description": "Blob ID",
        "name": "blobId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/blob-id.v1"
        }
      }
    },
    "headers": {
      "digestmd5.v1": {
        "description": "Base64-encoded MD5 hash of the resource, per [RFC 3230](https://www.ietf.org/rfc/rfc3230.txt)",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^md5=(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
          "minLength": 28,
          "maxLength": 28
        },
        "example": "md5=HUXZLQLMuI/KZ5KDcJPcOA=="
      }
    }
  }
}