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.