Skip to content

Upload & attach file

Attaching files (like images or documents) to form fields via the API usually involves two main steps for files stored locally on your system:

  1. Upload the file: Send the file content to Tallyfy’s file endpoint to get an asset reference.
  2. Update the task/process: Use the asset reference obtained in step 1 to update the corresponding task or process, linking the file to the specific form field.

Alternatively, for files already hosted publicly online, you might be able to link them directly in a single step (see Method 2 in the older article content, though this might be less common and subject to change - prioritize the upload method).

Step 1: Upload the File

Endpoint: POST /organizations/{org_id}/file

Request Type: multipart/form-data

This request uploads the raw file data. It requires specific form data fields to correctly categorize the upload.

Headers:

  • Authorization: Bearer {your_access_token}
  • Accept: application/json
  • X-Tallyfy-Client: APIClient
  • (Content-Type header will be set automatically by your HTTP client for multipart/form-data)

Form Data Fields (Required):

FieldDescriptionExample Value
nameThe actual file binary data.(Select file in your client)
uploaded_fromContext of upload. For Tasks, use the Form Field ID (Capture ID). For Kick-off, use ko_field.capture_id_abc123 or ko_field
subject_typeType of object the file relates to.Run (for Tasks) or Checklist (for Kick-off)
subject_idID of the object type.{run_id} (for Tasks) or {checklist_id} (for Kick-off)
sourceHow the file is provided.local
step_idRequired only for Tasks. The ID of the Step within the template that the task belongs to.step_id_xyz789
checklist_idRequired only for Tasks. The ID of the template (Checklist) that the process run was launched from.template_id_efg456

Code Samples (Step 1: Upload)

(Note: Handling multipart/form-data varies significantly between languages and libraries. These are conceptual examples.)

const accessToken = 'YOUR_PERSONAL_ACCESS_TOKEN';
const orgId = 'YOUR_ORGANIZATION_ID';
const apiUrl = `https://go.tallyfy.com/api/organizations/${orgId}/file`;
// --- For Task Field ---
const formFieldId = 'CAPTURE_ID_OF_FILE_FIELD';
const runId = 'PROCESS_RUN_ID';
const stepId = 'STEP_ID_CONTAINING_FIELD';
const checklistId = 'TEMPLATE_ID_OF_RUN';
// --- OR For Kick-off Field ---
// const prerunFieldId = 'PRERUN_FIELD_ID'; // Use ko_field generally for uploaded_from
// const checklistIdForKO = 'TEMPLATE_ID_WITH_KICKOFF';
// Assume 'fileInput' is an HTML <input type="file"> element
const fileInput = document.getElementById('yourFileInputId');
const file = fileInput.files[0];
if (!file) {
console.error("No file selected!");
// return or handle error
}
const formData = new FormData();
formData.append('name', file, file.name);
formData.append('source', 'local');
// --- Populate based on target (Task or Kick-off) ---
// Example for Task Field:
formData.append('uploaded_from', formFieldId);
formData.append('subject_type', 'Run');
formData.append('subject_id', runId);
formData.append('step_id', stepId);
formData.append('checklist_id', checklistId);
// Example for Kick-off Field:
// formData.append('uploaded_from', 'ko_field');
// formData.append('subject_type', 'Checklist');
// formData.append('subject_id', checklistIdForKO);
// --- End Target Specific ---
const headers = new Headers();
headers.append('Authorization', `Bearer ${accessToken}`);
headers.append('Accept', 'application/json');
headers.append('X-Tallyfy-Client', 'APIClient');
// Content-Type is set automatically by fetch for FormData
fetch(apiUrl, {
method: 'POST',
headers: headers,
body: formData
})
.then(response => {
if (!response.ok) {
// Error handling...
return response.json().then(errData => { throw new Error(/*...*/); }).catch(() => { throw new Error(/*...*/); });
}
return response.json();
})
.then(data => {
console.log('Successfully uploaded file. Asset data:');
console.log(JSON.stringify(data, null, 2));
// NOW PROCEED TO STEP 2 using data.data[0] (or similar based on actual response)
})
.catch(error => {
console.error('Error uploading file:', error);
});

Response (Step 1: Upload)

A successful upload returns 200 OK and a JSON response containing an array usually with one element: the asset object representing the uploaded file. You need this object for Step 2.

{
"data": [
{
"id": "asset_id_abc123xyz", // The Asset ID
"filename": "document.pdf",
"version": 1,
"step_id": "step_id_xyz789", // If uploaded for a task
"uploaded_from": "capture_id_abc123", // Form Field ID or ko_field
"subject": {
"id": "run_id_or_checklist_id",
"type": "Run" // or "Checklist"
},
"url": "/internal/url/not/usually/needed/directly",
"uploaded_at": "2024-05-21T10:00:00Z"
// Potentially other fields
}
]
}

Extract the entire object within the data array (e.g., response.data[0] in JavaScript) for the next step.

Step 2: Attach Uploaded File to Field

Now, use the asset object obtained from Step 1 to update the specific task or process run, linking the file to the form field.

Endpoint:

  • Process Task: PUT /organizations/{org_id}/runs/{run_id}/tasks/{task_id}
  • Kick-off Form: PUT /organizations/{org_id}/checklists/{checklist_id} (Modify the prerun field in the template update payload)

Request Type: application/json

Headers:

  • Authorization: Bearer {your_access_token}
  • Accept: application/json
  • X-Tallyfy-Client: APIClient
  • Content-Type: application/json

Body (JSON - for Task Field):

Update the task using its endpoint. The body should include a taskdata object targeting the file field ID.

{
"taskdata": {
"CAPTURE_ID_OF_FILE_FIELD": [
// Paste the entire asset object from Step 1 response here
{
"id": "asset_id_abc123xyz",
"filename": "document.pdf",
"version": 1,
"step_id": "step_id_xyz789",
"uploaded_from": "capture_id_abc123",
"subject": {
"id": "run_id_or_checklist_id",
"type": "Run"
},
"url": "...",
"uploaded_at": "..."
// Include all fields returned in Step 1 data[0]
}
]
}
// You can include other task updates here too (e.g., summary, deadline)
}

Body (JSON - for Kick-off Field):

Update the template using its endpoint. The body needs to include the prerun array, modifying the entry for your file field.

{
"prerun": [
// ... other prerun fields ...
{
"id": "PRERUN_FIELD_ID_FOR_FILE", // ID of the kick-off field
// Other prerun field properties like label, required, etc.
// MIGHT need to be included - check GET /template response
"value": [ // The value is an array containing the asset object
// Paste the entire asset object from Step 1 response here
{
"id": "asset_id_abc123xyz",
"filename": "document.pdf",
// ... all other fields from Step 1 data[0] ...
}
]
}
// ... other prerun fields ...
]
// Include other template updates if needed (e.g., title)
}

Response (Step 2: Attach)

A successful PUT request returns 200 OK and the updated Task or Checklist object, reflecting the file attachment in the taskdata or prerun.value respectively.