Working with Documents

Retrieving Document Information via API

Many of our endpoint responses include references to a related document object. These objects include the following fields:

🚧

Note: Currently, these objects also include contentandsecure_contentfields. Starting on March 1st, 2024 both the content and secure_contentfields included in our document objects will be deprecated. If you are storing or using these fields internally, you will need to update your integration as described below.

{
  "id": "<The unique identifier of the document>",
  "title": "<The title of the document file>",
  "time_limited_url": "<A pre-authenticated link to the file contents with a 24 hour time out>",
}

Understanding Time Limited Links

The time_limited_url can be broken up in two parts. The first is the base url which helps locate the file in our document store and defines the file extension. The base url structure is defined as:

domain = 'https://res.cloudinary.com/medallion/image/authenticated/<version_id>/medallion/'
file_path = one of '<xyz>/<abc>/' or '<xyz>/' depending on the file location
file_name = # the file name on our servers
file_extenstion = # one of pdf, png, jpg etc.

base_url = domain + file_location + filename + '.' + file_extension

The second is the query parameters which define the the validity period and authentication to retrieve the file:

query_params = '?__cld_token__=exp=<expiration_timestamp>~acl=<authentication_scheme>~hmac=<hashed_authentication_code>'

Downloading File Content

We recommend downloading your file content immediately once you receive a time limited link and storing it internally under your own static link. If you are not able to store your file content internally, you can instead store the file id and request new time limited links via /p/api/v1/documents/{id}/ to download your content in the future.

The following example explains how to download a file from a pre-authenticated link.

import requests
from urllib.parse import parse_qs, urlparse

time_limited_url = # The url (str) returned in one of our API endpoints

# Get the file extension from the time limited link and set your file name
file_exts = parse_qs(urlparse(time_limited_url).path).split(".").pop(1)
file_ext = file_exts[0]
new_file_name = 'your_file_name.' + file_ext

# Download the file bytes
response = requests.get(time_limited_url)

# Check for any HTTP errors
response.raise_for_status()

# Save the bytes to a local file
with open(new_file_name, "wb") as new_file:
    new_file.write(response.content)

# Or save it to a remote file store such as AWS S3
import boto3
s3 = boto3.client("s3")
s3.put_object(
    Body=response.content,
    Bucket=your_bucket_name,
    Key=new_file_name,
)

Handling Download Errors

The following errors can occur when downloading file content via a time limited link:

404: Not Found This error will appear if your link is expired or if any part of the file path or query params has been modified.

If you receive a 404 error the best resolution is to request a new time_limited_url via API. If you have the document id stored locally you request the document details including a new link as shown in the example below.

import requests

id = # Your document uuid string
url = f"https://api.medallion.co/p/api/v1/documents/{id}/"

headers = {
    "Accept": "application/json",
    "x-api-key": "APIKEY",
}

# Get document details
response = requests.get(url, headers=headers)

# Check for any HTTP errors
response.raise_for_status()

# Get the new link from the response
time_limited_url = response.text.get("time_limited_url")

Uploading Files

We accept document uploads to both provider and group profiles. Both endpoints identify the provider or group to associate with the file by including the uuid in the URL path. The following example explains how to upload a document to a provider profile. Group profile documents can be uploaded in a similar way via the group profile API.

headers = {"Accept": "application/json", "x-api-key": "YOUR-API-KEY"}

provider_pk = "" # The provider uuid
with open("./filename.pdf", "rb") as f:
  	# Set the document file and kind, kind is an enum available in the endpoint documentation
    data = {"title": "Your Title", "kind": ""}
    files = [("content", f)]
    
    # Upload the file
    response = requests.post(
        f"https://api.medallion.co/api/v1/org/providers/{provider_pk}/documents/",
        headers=headers,
        data=data,
        files=files,
    )
    
    # Check for any HTTP errors
    response.raise_for_status()