File uploading via the API (Preferred)

Send a GET request to the presigned URL with the file details:

  • fileName

  • fileSize (in bytes)

This will return a ref ID and a URL for uploading.

Endpoint: https://{yourSiteName}.teamwork.com/projects/api/v1/pendingfiles/presignedurl.json?fileName=test.txt&fileSize=1024

Response

{
"ref": "tf_...",
"url": "https://tw-bucket.s3.amazonaws.com/tf_...?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Date=20190413T083843Z&X-Amz-Expires=600&X-Amz-Security-Token=...&X-Amz-SignedHeaders=content-length%3Bhost%3Bx-amz-acl&X-Amz-Signature=..."
}

Send a PUT request to the link above, with the 'file' in the body of the request. Along with this, you need the following hearders:

  • X-Amz-Acl: public-read

  • Content-Length: (check description below)

Usually the tools/libraries already automatically add the Content-Length HTTP header whenever a file is attached, but if not, make sure the API request contains the Content-Length HTTP header with the uploaded file size in bytes. This size MUST match what was provided in fileSize of step 1.

Code Example

curl -v -i -X PUT --data-binary "@test.txt" --header "X-Amz-Acl: public-read" "https://tw-bucket.s3.amazonaws.com/..."

If successful you should get a 200 response.

Full script example with both steps above:

#!/bin/bash

usage() {
  echo "Usage: $0 <file-path> <installation> <api-token>"
  echo ""
  echo "  Where"
  echo "    file-path:    Location of the file to be uploaded"
  echo "    installation: Teamwork URL (e.g. 'https://myinstallation.teamwork.com')"
  echo "    api-token:    API token that can be found in the user profile"
  exit 1
}

command -v curl >/dev/null 2>&1 || { echo >&2 "Please install curl"; exit 1; }
command -v jq >/dev/null 2>&1 || { echo >&2 "Please install jq"; exit 1; }

filepath="$1"
if [ -z "${filepath}" ]; then
  echo "missing file path"
  usage
fi

installation="$2"
if [ -z "${installation}" ]; then
  echo "missing installation"
  usage
fi

apitoken="$3"
if [ -z "${apitoken}" ]; then
  echo "missing api token"
  usage
fi

if [[ ! ( -s "${filepath}" ) ]]; then
  echo "file does not exist or is empty"
  usage
fi

filename=$(basename -- "${filepath}")
filesize=$(wc -c ${filepath} | awk '{print $1}')

presigned_response=$(curl -s -u ${apitoken}:xxx "${installation}/projects/api/v1/pendingfiles/presignedurl.json?fileName=${filename}&fileSize=${filesize}")
if [ $? -ne 0 ]; then
  echo "failed to generate pre-signed URL"
  exit 2
fi

fileref=$(echo "${presigned_response}" | jq ".ref" | tr -d '"')
presigned_url=$(echo "${presigned_response}" | jq ".url" | tr -d '"')

upload_response=$(curl -s -X PUT --data-binary "@${filepath}" -w "%{http_code}" --header "X-Amz-Acl: public-read" "${presigned_url}")
if [ $? -ne 0 ]; then
  echo "failed to upload file to AWS S3"
  exit 3
fi
if [ "${upload_response}" != "200" ]; then
  echo "error while uploading file to AWS S3"
  exit 4
fi

echo "Upload successful!"
echo "File reference: ${fileref}"

You can now use the ref ID from the first GET request to attach it to an object eg. task.

To attach to a task: PUT: /tasks/{id}/files.json

{"todo-item": {"pendingFileAttachments": "tf_..."}}

Step 3 here follows this step.

Feedback

If you have any feedback or suggestions, feel free to contact us at api@teamwork.com.