Skip to content

Launch projects

Launch a process as an “empty shell” - effectively a “project”

Normally in Tallyfy - you would create a template and then launch it.

Sometimes however you need to launch an ad-hoc project - just a one-time set of tasks and you want to track that just like you track a process.

We offer the ability to launch an “empty process” with no tasks in it. This give you then ability to then add one-off tasks to it and track it just like a process.

To put it more simply - Tallyfy offers the ability to run simple one-off projects, not just repeatable processes from a pre-made template.

Here’s how you can launch a process without requiring a predefined template. This powerful feature enables AI assistants, automation tools, and integrations to create ad-hoc collections of tasks that are tracked together as a single process.

Overview

Tallyfy’s API supports creating processes without templates through a special parameter in the task creation endpoint. When you set separate_task_for_each_assignee: true, the system automatically:

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

This eliminates the need to create templates for one-time or dynamic processes.

API Endpoint

POST /api/organizations/{orgId}/tasks

Required Headers

Authorization: Bearer {access_token}
Content-Type: application/json

Key Parameter

The magic happens with this single parameter:

{
"separate_task_for_each_assignee": true
}

When set to true, this parameter triggers the creation of an empty process container that holds all the tasks.

Request Schema

Complete 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": "2024-12-31 17:00:00",
"everyone_must_complete": false,
"is_soft_start_date": true,
"started_at": "2024-12-01 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 all tasks (max 600 characters)
summarystringNoDescription or instructions for the tasks
ownersobjectYesContains arrays of users, guests, and/or groups
separate_task_for_each_assigneebooleanYesMust be true to create process without template
task_typestringYesType of task: “task”, “approval”, “expiring”, “email”, or “expiring_email”
deadlinestringYesDeadline in “YYYY-MM-DD HH:MM:SS” format
everyone_must_completebooleanNoSet to false for independent task completion (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_commentbooleanNoPrevent guests from commenting (default: false)
can_complete_only_assigneesbooleanNoOnly assignees can complete the task (default: false)
max_assignableintegerNoMaximum number of assignees (default: 0, meaning 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

When including form_fields, each field object must contain:

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

Important Notes:

  • 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 member of the group
  • The process uses a system “MISC” template that exists in every organization

Implementation Examples

async function createProcessWithoutTemplate(orgId, accessToken, taskData) {
const response = await fetch(
`https://api.tallyfy.com/api/organizations/${orgId}/tasks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: taskData.title,
summary: taskData.description || '',
owners: {
users: taskData.userIds || []
},
separate_task_for_each_assignee: true, // Critical parameter
task_type: 'task', // Required
deadline: taskData.deadline || getDefaultDeadline(), // Required
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();
// Extract process information
const processId = result.data?.run?.id;
const processUrl = result.data?.run?.permalink;
console.log(`Created process ${processId}: ${processUrl}`);
return result;
}
// Example: Create a process for multiple timesheet submissions
async function createTimesheetProcess() {
const taskData = {
title: 'Submit Weekly Timesheet',
description: 'Please submit your timesheet for this week by Friday 5pm',
userIds: ['user_123', 'user_456', 'user_789'],
deadline: '2024-12-13 17:00:00'
};
await createProcessWithoutTemplate('your-org-id', 'your-token', taskData);
}
function getDefaultDeadline() {
const date = new Date();
date.setDate(date.getDate() + 7);
return date.toISOString().slice(0, 19).replace('T', ' ');
}

Advanced Usage

Creating Multi-Stage Processes

For processes that require different tasks with unique titles and descriptions, use a two-stage approach:

  1. Stage 1: Create the first task with separate_task_for_each_assignee: true to establish the process
  2. Stage 2: Add additional tasks to the same process using the run_id from Stage 1
async function createMultiStageProcess(orgId, accessToken, tasks) {
// Stage 1: Create process with first task
const firstTask = tasks[0];
const processResponse = await fetch(
`https://api.tallyfy.com/api/organizations/${orgId}/tasks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'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', // Required
deadline: firstTask.deadline
})
}
);
const processResult = await processResponse.json();
const processId = processResult.data?.run?.id;
if (!processId) {
throw new Error('Failed to create process');
}
// Stage 2: Add remaining tasks to the process
for (let i = 1; i < tasks.length; i++) {
const task = tasks[i];
await fetch(
`https://api.tallyfy.com/api/organizations/${orgId}/tasks`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: task.title,
summary: task.description,
owners: { users: task.userIds },
run_id: processId, // Attach to existing process
task_type: 'task', // Required
deadline: task.deadline,
position: i + 1
})
}
);
}
return processId;
}
// Example: Create a multi-stage approval process
const approvalTasks = [
{
title: 'Prepare Budget Proposal',
description: 'Draft the Q1 budget proposal document',
userIds: ['user_123'],
deadline: '2024-12-10 17:00:00'
},
{
title: 'Review Budget Proposal',
description: 'Review and provide feedback on the proposal',
userIds: ['user_456'],
deadline: '2024-12-12 17:00:00'
},
{
title: 'Approve Budget Proposal',
description: 'Final approval of the Q1 budget',
userIds: ['user_789'],
deadline: '2024-12-15 17:00:00'
}
];
const processId = await createMultiStageProcess('org-id', 'token', approvalTasks);

Use Cases

1. AI Assistant Bulk Operations

Perfect for AI assistants that need to create tasks for multiple users:

// AI Assistant: "Ask 6 people to submit timesheets by Friday 5pm"
const timesheetRequest = {
title: "Submit Weekly Timesheet",
userIds: ["user1", "user2", "user3", "user4", "user5", "user6"],
description: "Please submit your timesheet for this week",
deadline: "2024-12-13 17:00:00"
};
await createProcessWithoutTemplate(orgId, token, timesheetRequest);
// Creates 1 process with 6 individual tasks, each trackable separately

2. Dynamic Approval Workflows

Create approval chains without predefined templates:

# Dynamic approval chain based on document type
approval_chain = determine_approval_chain(document_type) # Returns user IDs
creator.create_process_without_template(
title=f"Approve {document_type}",
user_ids=approval_chain,
description=f"Please review and approve the {document_type}",
deadline=datetime.now() + timedelta(days=3)
)

3. Event-Driven Task Creation

Respond to external events by creating processes:

// Webhook receives new customer signup
async function onNewCustomer(customerData) {
const onboardingTasks = {
title: `Onboard ${customerData.company}`,
userIds: [
salesRepId, // Welcome call
supportRepId, // Setup assistance
successManagerId // Success planning
],
description: `Complete onboarding for new customer: ${customerData.company}`,
deadline: getDeadline(7) // 7 days from now
};
await createProcessWithoutTemplate(orgId, token, onboardingTasks);
}

4. Batch Processing from Spreadsheets

Import tasks from external sources:

import pandas as pd
# Read tasks from CSV
df = pd.read_csv('monthly_tasks.csv')
for _, row in df.iterrows():
creator.create_process_without_template(
title=row['task_title'],
user_ids=row['assignees'].split(','),
description=row['description'],
deadline=datetime.strptime(row['due_date'], '%Y-%m-%d')
)

API Response

The API returns a single task object (the first task created) even though it creates tasks for all assignees. The response includes:

{
"data": {
"id": "task_id",
"title": "Task title",
"status": "not-started",
"deadline": "2024-12-31 17:00:00",
"run": {
"id": "process_id",
"name": "Task title",
"permalink": "https://app.tallyfy.com/...",
"started_at": "2024-12-01 09:00:00"
}
}
}

To track all created tasks, you’ll need to query the process using the returned run.id.

Important Considerations

Process Ownership

The user creating the process becomes the process owner automatically but is not assigned to the individual tasks unless explicitly included in the assignee list.

Task Independence

When everyone_must_complete is set to false (recommended), each assignee can complete their task independently, allowing for better progress tracking.

MISC System Checklist

Behind the scenes, Tallyfy uses a special “MISC” system checklist that exists in every organization. This is transparent to API users and requires no configuration.

Rate Limiting

When creating processes in bulk, implement appropriate rate limiting to avoid hitting API limits. Consider adding delays between requests for large batches.

Error Handling

Always implement proper error handling for production use:

try {
const result = await createProcessWithoutTemplate(orgId, token, taskData);
// Log success
console.log(`Process created: ${result.data.run.id}`);
// Store process ID for tracking
await storeProcessId(result.data.run.id);
} catch (error) {
// Handle specific error types
if (error.status === 401) {
// Token expired, refresh and retry
await refreshToken();
return retry();
} else if (error.status === 422) {
// Validation error
console.error('Invalid task data:', error.response.errors);
} else if (error.status === 429) {
// Rate limited, wait and retry
await sleep(60000);
return retry();
} else {
// Log unexpected errors
console.error('Unexpected error:', error);
throw error;
}
}

Testing Your Implementation

Use our test script to verify your implementation:

Terminal window
# Download test script
curl -O https://docs.tallyfy.com/examples/test_process_without_template.py
# Set environment variables
export TALLYFY_ORG_ID="your-org-id"
export TALLYFY_CLIENT_ID="your-client-id"
export TALLYFY_CLIENT_SECRET="your-client-secret"
# Run tests
python3 test_process_without_template.py

Best Practices

  1. Use Descriptive Titles: Since these processes don’t have templates, make titles clear and actionable
  2. Include Context in Descriptions: Provide sufficient context in the summary field
  3. Set Realistic Deadlines: Consider timezone differences and working hours
  4. Track Process IDs: Store returned process IDs for monitoring and reporting
  5. Implement Retry Logic: Handle transient failures gracefully
  6. Log All Operations: Maintain audit trails for compliance and debugging

Processes > Launch process

The Launch Process API endpoint enables creation of new process instances by sending a POST request with template details task assignments and kick-off field data while supporting various programming languages for integration.

Launching > Launch manually

Manual process launching in Tallyfy allows you to initiate workflow instances from templates with complete control over timing and customization by selecting a template naming the instance and clicking launch to create an active trackable process.

Pro > Launching

Tallyfy’s process launching feature transforms reusable workflow templates into active trackable instances with specific assignments and deadlines that operate independently through multiple launch methods including manual API webhooks forms email triggers and magic links while allowing customization during launch and protecting running processes from template changes.

Tasks > Create one-off task

The POST endpoint enables creation of standalone tasks with customizable fields like name description assignees deadline and tags through authenticated API requests that return task details upon successful creation.