Skip to content

Task operations and automation

Tasks are individual work items inside a running process. You can list, complete, update, and comment on tasks through the API using Postman.

Understanding task structure

In Tallyfy’s API:

  • Tasks - individual work items in a running process (or standalone one-off tasks)
  • Captures - form field values within tasks (saved via a separate endpoint)
  • Owners - who’s assigned to complete the task (users, guests, or groups)

Listing tasks

Get your assigned tasks

GET {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/me/tasks
Headers:
Authorization: Bearer {{TALLYFY_ACCESS_TOKEN}}
X-Tallyfy-Client: APIClient
Accept: application/json
Query parameters:
- status: active, completed, overdue, due_soon, hasproblem
- per_page: 10 (default)
- page: 1
- sort: deadline, newest, problems, -deadline

Get all tasks in a process

GET {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/runs/{{RUN_ID}}/tasks
Query parameters:
- status: active, complete, overdue, not-started, auto-skipped
- sort: position, deadline, -position, -deadline
- with: step,form_fields,threads,assets,summary

Filter tasks by various criteria

// Advanced filtering in Tests tab
const tasks = pm.response.json().data;
// Overdue tasks
const overdueTasks = tasks.filter(t =>
t.deadline && new Date(t.deadline) < new Date() && t.status === 'active'
);
// Tasks by specific assignee
const userTasks = tasks.filter(t =>
t.owners && t.owners.users && t.owners.users.some(u => u.id === 10001)
);
console.log(`Found ${overdueTasks.length} overdue tasks`);

Completing tasks

Task completion uses a POST to the completed-tasks endpoint, not a PUT. You send the task_id in the request body.

Complete a process task

POST {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/runs/{{RUN_ID}}/completed-tasks
Headers:
Authorization: Bearer {{TALLYFY_ACCESS_TOKEN}}
X-Tallyfy-Client: APIClient
Accept: application/json
Content-Type: application/json
Body:
{
"task_id": "{{TASK_ID}}",
"is_approved": true
}

The is_approved field is optional and only applies to approval-type tasks.

Complete a one-off task

POST {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/completed-tasks
Body:
{
"task_id": "{{TASK_ID}}"
}

Save form field data before completing

Form field values (captures) are saved through a separate endpoint before you complete the task:

POST {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/tasks/{{TASK_ID}}/captures
Body:
{
"id": "field_abc123",
"value": "Approved"
}

Each capture call saves one field at a time. Send multiple requests to fill several fields, then complete the task.

Bulk task completion

Complete multiple tasks in a process:

const runId = pm.environment.get("RUN_ID");
const taskIds = ["task_123", "task_456", "task_789"];
const results = [];
function completeTask(taskId) {
return new Promise((resolve, reject) => {
pm.sendRequest({
url: `${pm.environment.get("TALLYFY_BASE_URL")}/organizations/${pm.environment.get("TALLYFY_ORG_ID")}/runs/${runId}/completed-tasks`,
method: 'POST',
header: {
'Authorization': `Bearer ${pm.environment.get("TALLYFY_ACCESS_TOKEN")}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: {
mode: 'raw',
raw: JSON.stringify({ task_id: taskId })
}
}, (err, res) => {
if (err) {
reject(err);
} else {
resolve({ taskId, status: res.code });
}
});
});
}
async function completeTasks() {
for (let i = 0; i < taskIds.length; i++) {
try {
const result = await completeTask(taskIds[i]);
results.push(result);
console.log(`Completed task ${i + 1} of ${taskIds.length}`);
if (i < taskIds.length - 1) {
await new Promise(resolve => setTimeout(resolve, 200));
}
} catch (error) {
console.error(`Failed to complete task ${taskIds[i]}:`, error);
}
}
console.log('Bulk completion results:', results);
}
completeTasks();

File attachments

Upload a file

File uploads use the assets endpoint with multipart/form-data.

  1. Set up the request

    POST {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/assets
    Headers:
    Authorization: Bearer {{TALLYFY_ACCESS_TOKEN}}
    X-Tallyfy-Client: APIClient
    Accept: application/json
    // DO NOT set Content-Type - let Postman handle it
  2. Configure body as form-data

    • Select Body then form-data
    • Add key: file (type: File)
    • Add key: subject_id (type: Text, value: the task ID)
    • Add key: subject_type (type: Text, value: task)
  3. Select file

    • Click Select Files for the file field
    • Choose your file
    • Send request

Tips from Postman experts:

  • Don’t set Content-Type manually - Postman automatically sets multipart/form-data with the correct boundary. Setting it yourself causes “Missing start boundary” errors.
  • Boundary handling - the boundary separates form parts. Postman generates it automatically.

Download a file

GET {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/download-files/{{FILE_ID}}
Headers:
Authorization: Bearer {{TALLYFY_ACCESS_TOKEN}}
X-Tallyfy-Client: APIClient
Accept: application/json

Save the response using Postman’s “Save Response” then “Save to a file” option.

Task assignment patterns

Reassign a task

Update task assignments using the owners object with users, guests, and groups sub-fields:

PUT {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/runs/{{RUN_ID}}/tasks/{{TASK_ID}}
Body:
{
"owners": {
"users": [10001, 10002],
"guests": ["contractor@example.com"],
"groups": []
}
}

Dynamic assignment based on workload

Assign to the least busy team member:

async function assignToLeastBusy(runId, taskId) {
// Get task counts for candidate users
const userIds = [10001, 10002, 10003];
const taskCounts = await Promise.all(userIds.map(async (userId) => {
const tasksResponse = await new Promise((resolve, reject) => {
pm.sendRequest({
url: `${pm.environment.get("TALLYFY_BASE_URL")}/organizations/${pm.environment.get("TALLYFY_ORG_ID")}/users/${userId}/tasks?status=active&without_pagination=true`,
method: 'GET',
header: {
'Authorization': `Bearer ${pm.environment.get("TALLYFY_ACCESS_TOKEN")}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json'
}
}, (err, res) => err ? reject(err) : resolve(res));
});
return {
userId,
taskCount: tasksResponse.json().data.length
};
}));
const leastBusy = taskCounts.reduce((prev, current) =>
prev.taskCount < current.taskCount ? prev : current
);
console.log(`Assigning to user ${leastBusy.userId} (${leastBusy.taskCount} active tasks)`);
// Assign the task
return new Promise((resolve, reject) => {
pm.sendRequest({
url: `${pm.environment.get("TALLYFY_BASE_URL")}/organizations/${pm.environment.get("TALLYFY_ORG_ID")}/runs/${runId}/tasks/${taskId}`,
method: 'PUT',
header: {
'Authorization': `Bearer ${pm.environment.get("TALLYFY_ACCESS_TOKEN")}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: {
mode: 'raw',
raw: JSON.stringify({
owners: { users: [leastBusy.userId] }
})
}
}, (err, res) => err ? reject(err) : resolve(res));
});
}

Working with task comments

Add a comment to a task

The comment endpoint uses the singular /comment, not /comments:

POST {{TALLYFY_BASE_URL}}/organizations/{{TALLYFY_ORG_ID}}/tasks/{{TASK_ID}}/comment
Headers:
Authorization: Bearer {{TALLYFY_ACCESS_TOKEN}}
X-Tallyfy-Client: APIClient
Accept: application/json
Content-Type: application/json
Body:
{
"content": "Please review the attached documents before approving."
}

Task escalation for overdue items

Find and escalate overdue tasks:

const tasks = pm.response.json().data;
const now = new Date();
const overdueTasks = tasks.filter(t => {
if (!t.deadline || t.status !== 'active') return false;
return new Date(t.deadline) < now;
});
overdueTasks.forEach(task => {
const hoursOverdue = Math.floor((now - new Date(task.deadline)) / (1000 * 60 * 60));
pm.sendRequest({
url: `${pm.environment.get("TALLYFY_BASE_URL")}/organizations/${pm.environment.get("TALLYFY_ORG_ID")}/tasks/${task.id}/comment`,
method: 'POST',
header: {
'Authorization': `Bearer ${pm.environment.get("TALLYFY_ACCESS_TOKEN")}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: {
mode: 'raw',
raw: JSON.stringify({
content: `ESCALATION: This task is ${hoursOverdue} hours overdue. Manager notified.`
})
}
});
});

Troubleshooting task operations

”Cannot complete task” errors

Common causes:

  • Task already completed
  • You aren’t assigned to the task (and can_complete_only_assignees is on)
  • Required form fields haven’t been filled (save captures first)
  • Previous dependencies aren’t complete yet

File upload issues

  • Use multipart/form-data, not JSON
  • Don’t manually set Content-Type - let Postman handle it
  • Include subject_id and subject_type fields

Pagination

Task list endpoints use page and per_page (default 10), not limit/offset:

GET .../me/tasks?status=active&per_page=50&page=1

Set without_pagination=true to get all results in one response.

Next steps

With task automation set up:

Workato > Complete Tallyfy tasks from Workato

Workato recipes can programmatically complete Tallyfy tasks using HTTP requests to the task completion endpoint with proper authentication and form field data, triggered by events in systems like DocuSign or CRM platforms.

Tasks > Complete task

Mark Tallyfy tasks as complete using POST requests to different endpoints for process tasks versus standalone tasks, with approval status support.

Tasks > Update task

Update existing Tallyfy tasks via PUT API endpoints for both process tasks and one-off tasks - modify title deadline assignees and form field values through taskdata objects with field-type-specific formatting for text dropdowns radio buttons and checkboxes.

Postman > Working with templates and processes

Working with Tallyfy templates and processes through the API in Postman requires understanding that the API uses “checklists” for templates and “runs” for processes, with process creation done via POST to the runs endpoint with a checklist_id in the request body.