Clio Documents API
Clio Documents are files uploaded to Clio. Files uploaded to Clio’s document integrations (e.g. Google Drive and Office365) are inaccessible through the API. [Support Link](https://help.clio.com/hc/en-us/articles/9290308200091-Generate-Manage-and-Share-Documents#create-upload-and-share-documents-in-clio-manage-0-3) ## Uploading a new document [Create a document](#operation/Document%23create) to a parent that can refer to a `Matter` or a `Folder`. Ensure to ask for the fields, `id` and `latest_document_version{uuid,put_url,put_headers}`. The `put_url` is a signed URL with security credentials for uploading the document. The `put_headers` are required request headers for uploading the document. Check out the example to upload a new document to the matter folder of `Matter` with id `1`: ```json Request POST api/v4/documents?fields=id,latest_document_version{uuid,put_url,put_headers} "data": { "name": "file.jpg", "parent": { "id": 1, "type": "Matter" } } Response { "data": { "id": 1234, "latest_document_version": { "uuid": "a51faa2c-859e-4c08-a996-2d0bb385df90", "put_url": "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/a51faa2c-859e-4c08-a996-2d0bb385df90/file.jpg?X-Amz-Expires=28800&X-Amz-Date=20171024T214532Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_key}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-server-side-encryption&X-Amz-Signature=afe5000df0972d02884a2219f913bfa62fe2531c75b4fcd1edbcb84d267d2b8e", "put_headers": [ { "name": "x-amz-server-side-encryption", "value": "AES256" }, { "name": "Content-Type", "value": "image/jpeg" } ] } } } ``` If the extension is listed in the [IANA Media Types registry](https://www.iana.org/assignments/media-types/media-types.xhtml) Clio will apply the corresponding content type as determined by the file extension when `content_type` is blank. One of the nine possible content types `content_type` = “text” / “image” / “audio” / “video” / “application” / “font” / “model” / “message” / “multipart” must be submitted if the file type is uncommon, not listed in the [IANA Media Types registry](https://www.iana.org/assignments/media-types/media-types.xhtml) or not obvious from the extension. ### Upload the document Upload the document to the `put_url` with the headers from `puts_headers` given in the response of the previous step. Typically the headers include `Content-Type` and `x-amz-server-side-encryption` to match with the signature in the `put_url`. Check out the example to upload the file content using curl: ```bash curl -X PUT -T file.jpg -H "Content-Type: image/jpeg" -H "x-amz-server-side-encryption: AES256" "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/a51faa2c-859e-4c08-a996-2d0bb385df90/file.jpg?X-Amz-Expires=28800&X-Amz-Date=20171024T214532Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_key}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-server-side-encryption&X-Amz-Signature=afe5000df0972d02884a2219f913bfa62fe2531c75b4fcd1edbcb84d267d2b8e" ``` If you need MD5 checksum, you should use multipart upload. ### Mark the document as fully-uploaded After successfully completing the upload, [mark the document fully uploaded](#operation/Document%23update) with `fully_uploaded` as `true`, and `uuid` given in the first step. Clio will verify if the file is uploaded successfully. If not, it raises `UploadNotFoundError` error. It is possible for the verification to time out, which will return an `UploadTimeoutError` error. When that happens, you will need to retry the request. ```json Request PATCH api/v4/documents/1234?fields=id,latest_document_version{fully_uploaded} "data": { "uuid": "a51faa2c-859e-4c08-a996-2d0bb385df90", "fully_uploaded": "true" } } Response (success) { "data": { "id": 12345, "latest_document_version": { "fully_uploaded": true } } } Response (error) { "error": { "type": "UploadNotFoundError", "message": "A matching remote file was not found for the file named file.jpg with UUID a51faa2c-859e-4c08-a996-2d0bb385df90" } } Response (timeout) { "error": { "type": "UploadTimeoutError", "message": "A timeout occurred verifying the remote file. Please try the request again." } } ``` The file is now visible in Clio documents and is available to the user for download. ## Uploading a new document version It is same as uploading a new document to Clio except setting the `parent` to an existing `Document`. Check out the example to upload a new document version for the document with id `1234`: ```json Request POST api/v4/documents?fields=id,latest_document_version{uuid,put_url,put_headers} "data": { "name": "file.jpg", "parent": { "id": 1234, "type": "Document" } } } ``` The remaining steps are same as uploading a new document to Clio. ## Uploading a document using multipart upload In general, when a file reaches 100 MB, you should consider using multipart upload instead of uploading in a single operation. Except the last part, each part should be at least 5 MB. Determine the number of file parts and split the file. Optionally, you may compute the base64-encoded 128-bit MD5 mechanism as an end-to-end integrity check for each file part. To determine the base64 MD5 checksum for a file part, you may use `openssl`. Check out the example to split a big pdf and get the checksums of the file parts: ```bash split -b 31457280 big.pdf big.pdf. # break the file to max. 30MB size openssl md5 -binary big.pdf.aa | base64 # F16pda4G0h4lzH7d2/Jbdw== openssl md5 -binary big.pdf.ab | base64 # cRbxEG//GK9rIze5tdYzcg== openssl md5 -binary big.pdf.ac | base64 # Tck0KKU4SrmSp8hsSCuSYg== openssl md5 -binary big.pdf.ad | base64 # CrIt7lbZzVhMV7JzVTkUvw== ``` ### Create the document [Create a document](#operation/Document%23create), specify `multiparts` for multipart upload, and ensure to ask for the fields, `id`, and `latest_document_version{uuid,multiparts}`. A `multipart` consists of `part_number`, `content_length`, and optional `content_md5`. In the response, a `put_url` is appended to the `multipart`. A `put_url` is a signed URL with security credentials for uploading a file part. The signed URL expires in 8 hours. The API can handle maximum 50 `multiparts` in one request. If the upload is split to more than 50 parts, [make a PUT request](#operation/Document%23update) with `uuid`, `fully_uploaded` as `false`, and another set of `multiparts`. It returns a set of `put_url` for the specified `multiparts`. Check out the example to upload a new document to the matter folder of `Matter` with id `1`: ```json Request POST api/v4/documents?fields=id,latest_document_version{uuid,put_headers,multiparts} "data": { "name": "big.pdf", "parent": { "id": 1, "type": "Matter" } "multiparts": [ { "part_number": 1, "content_length": 31457280, "content_md5": "F16pda4G0h4lzH7d2/Jbdw==" }, { "part_number": 2, "content_length": 31457280, "content_md5": "cRbxEG//GK9rIze5tdYzcg==" }, { "part_number": 3, "content_length": 31457280, "content_md5": "Tck0KKU4SrmSp8hsSCuSYg==" }, { "part_number": 4, "content_length": 7316647, "content_md5": "CrIt7lbZzVhMV7JzVTkUvw==" } ] } Response { "data": { "id": 1234, "latest_document_version": { "uuid": "eba78724-31e8-4529-b6e2-0f2eef6feeec", "put_headers": [ { "name": "x-amz-server-side-encryption", "value": "AES256" }, { "name": "Content-Type", "value": "application/pdf" } ], "multiparts": [ { "part_number": 1, "put_url": "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/eba78724-31e8-4529-b6e2-0f2eef6feeec/big.pdf?uploadId=XG9arnSRfpXVFj4NYCoj66e.iUtET050CFds7GGwb4_J6J26Ysgn_fLCK7pI5KRzJRmBOB_Oa.dle.nn4JLKos_cdRXN6f6Hb0IACkgiN6Wa2XGNv9fZQwgfqmMey1DN&partNumber=1&X-Amz-Expires=28800&X-Amz-Date=20171024T231538Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_token}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-md5%3Bhost&X-Amz-Signature=f7b3f29e4aee3abfa93fb42a7969557a2a0d305d223dde641c78421b5a6d62e0", "put_headers": [ { "name": "Content-Length", "value": "31457280" }, { "name": "Content-MD5", "value": "F16pda4G0h4lzH7d2/Jbdw==" } ] }, { "part_number": 2, "put_url": "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/eba78724-31e8-4529-b6e2-0f2eef6feeec/big.pdf?uploadId=XG9arnSRfpXVFj4NYCoj66e.iUtET050CFds7GGwb4_J6J26Ysgn_fLCK7pI5KRzJRmBOB_Oa.dle.nn4JLKos_cdRXN6f6Hb0IACkgiN6Wa2XGNv9fZQwgfqmMey1DN&partNumber=2&X-Amz-Expires=28800&X-Amz-Date=20171024T231538Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_token}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-md5%3Bhost&X-Amz-Signature=47dc30f90202654c13030ccce87e43622bb47e0ad155ae61f6b41e8097803950", "put_headers": [ { "name": "Content-Length", "value": "31457280" }, { "name": "Content-MD5", "value": "cRbxEG//GK9rIze5tdYzcg==" } ] }, { "part_number": 3, "put_url": "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/eba78724-31e8-4529-b6e2-0f2eef6feeec/big.pdf?uploadId=XG9arnSRfpXVFj4NYCoj66e.iUtET050CFds7GGwb4_J6J26Ysgn_fLCK7pI5KRzJRmBOB_Oa.dle.nn4JLKos_cdRXN6f6Hb0IACkgiN6Wa2XGNv9fZQwgfqmMey1DN&partNumber=3&X-Amz-Expires=28800&X-Amz-Date=20171024T231538Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_token}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-md5%3Bhost&X-Amz-Signature=13ca827a73fb2c50e8062ef7e437cfe9158944d998e2770a2ffcd034be6c2fc7", "put_headers": [ { "name": "Content-Length", "value": "31457280" }, { "name": "Content-MD5", "value": "Tck0KKU4SrmSp8hsSCuSYg==" } ] }, { "part_number": 4, "put_url": "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/eba78724-31e8-4529-b6e2-0f2eef6feeec/big.pdf?uploadId=XG9arnSRfpXVFj4NYCoj66e.iUtET050CFds7GGwb4_J6J26Ysgn_fLCK7pI5KRzJRmBOB_Oa.dle.nn4JLKos_cdRXN6f6Hb0IACkgiN6Wa2XGNv9fZQwgfqmMey1DN&partNumber=4&X-Amz-Expires=28800&X-Amz-Date=20171024T231538Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_token}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-md5%3Bhost&X-Amz-Signature=25773f971c4c663b3a87f4d35c5b4c5192c3c999c7efdd69a49bc5bc40677078", "put_headers": [ { "name": "Content-Length", "value": "7316647" }, { "name": "Content-MD5", "value": "CrIt7lbZzVhMV7JzVTkUvw==" } ] } ] } } } ``` ### Upload the document Upload each multipart to the corresponding `put_url`. You can upload the parts independently and in any order. If transmission of any part fails, you can re-transmit that part without affecting other parts. Make sure to include the headers from `puts_headers`. Typically the headers include `Content-Length`, to match with the signature in the `put_url`. Check out the example using curl: ```bash curl -X PUT -T big.pdf.part1 -H "Content-Length: 31457280" "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/eba78724-31e8-4529-b6e2-0f2eef6feeec/big.pdf?uploadId=XG9arnSRfpXVFj4NYCoj66e.iUtET050CFds7GGwb4_J6J26Ysgn_fLCK7pI5KRzJRmBOB_Oa.dle.nn4JLKos_cdRXN6f6Hb0IACkgiN6Wa2XGNv9fZQwgfqmMey1DN&partNumber=1&X-Amz-Expires=28800&X-Amz-Date=20171024T231538Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_token}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-md5%3Bhost&X-Amz-Signature=f7b3f29e4aee3abfa93fb42a7969557a2a0d305d223dde641c78421b5a6d62e0" ``` If you use MD5 checksum to validate the integrity of upload, include `Content-MD5` in the header: ```bash curl -X PUT -T big.pdf.part1 -H "Content-Length: 31457280" -H "Content-MD5: F16pda4G0h4lzH7d2/Jbdw==" "https://s3.us-west-2.amazonaws.com/iris-production/uploads/document_version/file/eba78724-31e8-4529-b6e2-0f2eef6feeec/big.pdf?uploadId=XG9arnSRfpXVFj4NYCoj66e.iUtET050CFds7GGwb4_J6J26Ysgn_fLCK7pI5KRzJRmBOB_Oa.dle.nn4JLKos_cdRXN6f6Hb0IACkgiN6Wa2XGNv9fZQwgfqmMey1DN&partNumber=1&X-Amz-Expires=28800&X-Amz-Date=20171024T231538Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={aws_access_token}/20171024/us-west-2/s3/aws4_request&X-Amz-SignedHeaders=content-length%3Bcontent-md5%3Bhost&X-Amz-Signature=f7b3f29e4aee3abfa93fb42a7969557a2a0d305d223dde641c78421b5a6d62e0" ``` If the file is invalid or the MD5 is invalid, you may get the following response: ```bash BadDigest The Content-MD5 you specified did not match what we received. F16pda4G0h4lzH7d2/Jbdw== Tck0KKU4SrmSp8hsSCuSYg== 85918626116672DD AbAoiqYqn8tKwS6gxwI3pc4u02B6u6ORa6MPEJH7IYljBweZp0M8L7Lg2AFOvHxdHz5TwlQpkVs= ``` After the issue is corrected, try to upload to the file part to the `put_url` again. ### Mark the document as fully-uploaded After successfully completing the upload of all the file parts, [mark the document fully uploaded](#operation/Document%23update) with `fully_uploaded` as `true`, and `uuid` given in the first step. Clio will verify if the file is uploaded successfully. If not, it raises `UploadNotFoundError` error. It is possible for the verification to time out, which will return an `UploadTimeoutError` error. When that happens, you will need to retry the request. ```json Request PATCH api/v4/documents/1234?fields=id,latest_document_version{fully_uploaded} "data": { "uuid": "eba78724-31e8-4529-b6e2-0f2eef6feeec", "fully_uploaded": "true" } } Response (success) { "data": { "id": 12345, "latest_document_version": { "fully_uploaded": true } } } Response (error) { "error": { "type": "UploadNotFoundError", "message": "A matching remote file was not found for the file named file.jpg with UUID a51faa2c-859e-4c08-a996-2d0bb385df90" } } Response (timeout) { "error": { "type": "UploadTimeoutError", "message": "A timeout occurred verifying the remote file. Please try the request again." } } ``` The file is now visible in Clio documents and is available to the user for download. ## Uploading a new document version using multipart upload It is same as splitting and uploading a new document using multipart upload, except setting the `parent` to an existing `Document`. Check out the example to upload a new document version for the document with id `1234`: ```bash Request POST api/v4/documents?fields=id,latest_document_version{uuid,put_headers,multiparts} "data": { "name": "big.pdf", "parent": { "id": 1234, "type": "Document" } "multiparts": [ { "part_number": 1, "content_length": 31457280, "content_md5": "F16pda4G0h4lzH7d2/Jbdw==" }, { "part_number": 2, "content_length": 31457280, "content_md5": "cRbxEG//GK9rIze5tdYzcg==" }, { "part_number": 3, "content_length": 31457280, "content_md5": "Tck0KKU4SrmSp8hsSCuSYg==" }, { "part_number": 4, "content_length": 7316647, "content_md5": "CrIt7lbZzVhMV7JzVTkUvw==" } ] } ``` The remaining steps are same as uploading a new document to Clio.