Skip to content

Launch projects

Launch a process as an “empty shell” project

Normally in Tallyfy, you’d create a template and then launch it. But sometimes you need an ad-hoc project — just a one-time set of tasks you want to track like a regular process.

Tallyfy lets you launch an “empty process” with no predefined steps. You can then add one-off tasks to it and track everything together. Think of it as running simple one-off projects, not just repeatable processes from a template.

How it works

The one-off task creation endpoint (POST /organizations/{org_id}/tasks) accepts a separate_task_for_each_assignee parameter. When you set it to true, the system:

  1. Creates an empty process using the internal MISC system template
  2. Creates individual tasks — one for each assignee
  3. Links all tasks to that process for unified tracking

API endpoint

POST https://go.tallyfy.com/api/organizations/{org_id}/tasks

Required headers

HeaderValueRequired
AuthorizationBearer {access_token}Yes
X-Tallyfy-ClientAPIClientYes
Acceptapplication/jsonYes
Content-Typeapplication/jsonYes

Request body

{
"title": "Task title",
"summary": "Optional task description",
"owners": {
"users": ["userId1", "userId2", "userId3"],
"guests": ["guest@example.com"],
"groups": ["groupId1"]
},
"separate_task_for_each_assignee": true,
"task_type": "task",
"deadline": "YYYY-MM-DD 17:00:00",
"everyone_must_complete": false,
"is_soft_start_date": true,
"started_at": "YYYY-MM-DD 09:00:00",
"prevent_guest_comment": false,
"can_complete_only_assignees": false,
"max_assignable": 0,
"webhook": "https://your-webhook.com/endpoint",
"tags": ["tagId1", "tagId2"],
"top_secret": false,
"form_fields": [
{
"label": "Project Name",
"field_type": "text",
"required": true,
"guidance": "Enter the project name",
"position": 1
}
]
}

Parameter details

ParameterTypeRequiredDescription
titlestringYesTitle for the process and tasks (max 600 characters)
task_typestringYesOne of: task, approval, expiring, email, expiring_email
ownersobjectYesContains arrays of users, guests, and/or groups
deadlinestringYesDeadline in YYYY-MM-DD HH:MM:SS format
separate_task_for_each_assigneebooleanNoSet to true to create an empty process container. When omitted or false, a standalone one-off task is created instead.
summarystringNoDescription or instructions for the tasks
everyone_must_completebooleanNoWhether all assignees must complete the task (default: false)
is_soft_start_datebooleanNoWhether the start date is flexible (default: false)
started_atstringNoStart date in YYYY-MM-DD HH:MM:SS format (defaults to current time)
prevent_guest_commentbooleanNoBlock guests from commenting (default: false)
can_complete_only_assigneesbooleanNoOnly assignees can complete the task (default: false)
max_assignableintegerNoMaximum assignees allowed (default: 0 = unlimited)
webhookstringNoURL for webhook notifications on task events
tagsarrayNoArray of tag IDs (32-character strings)
top_secretbooleanNoMark task as confidential (default: false)
form_fieldsarrayNoArray of form field definitions for data collection

Form fields structure

Each object in form_fields supports:

Field PropertyTypeRequiredDescription
labelstringYesDisplay label for the field
field_typestringYesOne of: text, textarea, radio, dropdown, multiselect, number, email, url, date, time, datetime, checkbox, file
requiredbooleanYesWhether the field is mandatory
optionsarrayConditionalRequired for radio, dropdown, and multiselect types
guidancestringNoHelp text for the field
positionintegerNoDisplay order

Things to know:

  • Guest assignees must be email addresses, not IDs
  • The API returns only the first created task, but creates tasks for all assignees
  • When groups are specified, tasks are created for each group member
  • The process uses a system “MISC” template that exists in every organization

Code samples

async function createProcessWithoutTemplate(orgId, accessToken, taskData) {
const response = await fetch(
`https://go.tallyfy.com/api/organizations/${orgId}/tasks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: taskData.title,
summary: taskData.description || '',
owners: {
users: taskData.userIds || []
},
separate_task_for_each_assignee: true,
task_type: 'task',
deadline: taskData.deadline || getDefaultDeadline(),
everyone_must_complete: false,
is_soft_start_date: true
})
}
);
if (!response.ok) {
throw new Error(`Failed to create process: ${response.status}`);
}
const result = await response.json();
// The run (process) info is included when separate_task_for_each_assignee is true
const processId = result.data?.run?.id;
console.log(`Created process: ${processId}`);
return result;
}
function getDefaultDeadline() {
const date = new Date();
date.setDate(date.getDate() + 7);
return date.toISOString().slice(0, 19).replace('T', ' ');
}

Adding more tasks to the same process

If your process needs different tasks with unique titles, use a two-step approach:

  1. Create the first task with separate_task_for_each_assignee: true to establish the process
  2. Add more tasks to that process by passing the run_id from step 1
async function createMultiStageProcess(orgId, accessToken, tasks) {
// Step 1: Create process with the first task
const firstTask = tasks[0];
const processResponse = await fetch(
`https://go.tallyfy.com/api/organizations/${orgId}/tasks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: firstTask.title,
summary: firstTask.description,
owners: { users: firstTask.userIds },
separate_task_for_each_assignee: true,
task_type: 'task',
deadline: firstTask.deadline
})
}
);
const processResult = await processResponse.json();
const processId = processResult.data?.run?.id;
if (!processId) {
throw new Error('Failed to create process');
}
// Step 2: Add remaining tasks to the process
for (let i = 1; i < tasks.length; i++) {
const task = tasks[i];
await fetch(
`https://go.tallyfy.com/api/organizations/${orgId}/tasks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'X-Tallyfy-Client': 'APIClient',
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: task.title,
summary: task.description,
owners: { users: task.userIds },
run_id: processId,
task_type: 'task',
deadline: task.deadline,
position: i + 1
})
}
);
}
return processId;
}

API response

The API returns the first created task. When separate_task_for_each_assignee is true, the response includes the linked process (run) data:

{
"data": {
"id": "task_id",
"title": "Task title",
"status": "not-started",
"deadline": "YYYY-MM-DD 17:00:00",
"run": {
"id": "process_id",
"name": "Task title",
"started_at": "YYYY-MM-DD 09:00:00"
}
}
}

To see all created tasks, query the process using the returned run.id.

Good to know

Process ownership

The user making the API call becomes the process owner automatically, but won’t be assigned to individual tasks unless explicitly included in the assignee list.

Task independence

With everyone_must_complete set to false (the default), each assignee can complete their task independently.

MISC system template

Behind the scenes, Tallyfy uses a special “MISC” system template that exists in every organization. You don’t need to configure anything — it’s handled automatically.

Rate limiting

The API allows 600 requests per minute. When creating processes in bulk, keep this limit in mind and add delays between requests for large batches.

Error handling

try {
const result = await createProcessWithoutTemplate(orgId, token, taskData);
console.log(`Process created: ${result.data.run.id}`);
} catch (error) {
if (error.status === 401) {
// Token expired -- refresh and retry
await refreshToken();
return retry();
} else if (error.status === 422) {
// Validation error (missing required fields, invalid task_type, etc.)
console.error('Invalid task data:', error.response.errors);
} else if (error.status === 429) {
// Rate limited -- wait and retry
await sleep(60000);
return retry();
} else {
console.error('Unexpected error:', error);
throw error;
}
}

Tips

  1. Use clear titles — since these processes don’t come from templates, descriptive titles help everyone understand what’s going on
  2. Add context in summary — give assignees enough information to act on the task
  3. Set realistic deadlines — account for timezone differences and working hours
  4. Store the run.id — you’ll need it to track progress and add more tasks later
  5. Handle failures gracefully — implement retry logic for transient errors

Tasks > Create one-off task

Create standalone one-off tasks in Tallyfy via a POST request with required fields like title, task type, owners, and deadline.

Processes > Launch process

Launch a new Tallyfy process from a template using POST /organizations/[org_id]/runs with checklist_id and optional fields for kick-off form data, task assignments, and deadlines.

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.

Pro > Launching

Tallyfy lets you launch reusable templates into independent trackable processes — each with its own name and deadlines and assignments — through six different methods including manual clicks and API calls and email triggers and magic links while template edits only affect future launches and never alter already-running work.