Update task
Endpoint
Section titled “Endpoint”Use a different URL depending on the task type:
- Process task:
PUT /organizations/{org_id}/runs/{run_id}/tasks/{task_id} - One-off task:
PUT /organizations/{org_id}/tasks/{task_id}
Replace {org_id}, {run_id} (if applicable), and {task_id} with actual IDs.
Request
Section titled “Request”Headers
Section titled “Headers”Authorization: Bearer {your_access_token}Accept: application/jsonX-Tallyfy-Client: APIClientContent-Type: application/json
Body (JSON)
Section titled “Body (JSON)”Send a JSON object with only the fields you want to change. Updatable fields include:
title(string): New task title. Max 600 characters.summary(string): New task description.deadline(string): New deadline in ISO 8601 format (e.g.,YYYY-MM-DDTHH:mm:ssZ). Deadlines are automatically adjusted to the organization’s working days.started_at(string): Set or change the start date/time.owners(object): Update assignees. Structure:{ "users": [user_id1, ...], "guests": ["guest@email.com", ...], "groups": [group_id1, ...] }. This replaces existing assignees.taskdata(object): Update form field values (see details below).webhook(string): Update the task-specific webhook URL.prevent_guest_comment(boolean): Enable/disable guest comments.position(integer): Change the task’s position order.max_assignable(integer): Set the maximum number of assignees.
Updating form fields with taskdata
Section titled “Updating form fields with taskdata”Include a taskdata object in the request body. Keys are form field timeline IDs, and values depend on the field type.
taskdata and the prerun object used when launching a process run through the same validator, so the value shapes below are identical on both surfaces.
| Field type | Value to send |
|---|---|
| Short text | A plain string, max 200 characters |
| Long text (textarea) | A plain string, max 30,000 characters |
| A plain string | |
| Date | An ISO 8601 string: "2025-12-31T23:59:59Z" |
| Radio button | The option’s text as a bare string: "Full-time" |
| Dropdown | One object with both keys: { "id": 3, "text": "Office 365", "value": null } |
| Checklist (multi-select) | A list of those objects, each with "selected": [{ "id": 1, "text": "Slack", "selected": true }] |
| Table | A flat list with one entry per column, in column order: ["Widget", "3"] |
| Assignees | { "users": [12345], "guests": ["guest@example.com"], "groups": ["group_id"] } |
| File/Image | A list of file objects. See Attach files using the API - files must be uploaded first. |
Three shapes catch people out:
- Radio and dropdown look identical in the app but differ here. A radio takes the bare option text. A dropdown needs the
idandtextpair together, and thetexthas to match the option exactly. - Every chosen multi-select option needs
"selected": true. Without it the value still saves and you still get a200, but the field renders as empty text wherever it’s used as a{{variable}}. A blank multi-select in a task description or an email is nearly always a missingselectedflag. - A table takes one entry per column, not per row. Send a different number of entries and the request fails with
Number of columns does not match required columns.
Multiple field types in one call
Section titled “Multiple field types in one call”{ "taskdata": { "e4238158ad0949d4ad78c55125b28a99": "normal text field", // Short text "ad789434de1c4d5fade2193d237c5716": "Text Area content here", // Long text/textarea "7a54e215a9904096851360917080599f": "yes", // Radio button "8c0161f92eba4d3da7182fed348f3421": "2025-12-20T14:23:18.128Z", // Date field "0e4b280880cc4407a06478a2faa8052b": { // Dropdown selection "id": 2, "text": "Office 365", "value": null }, "fe316c2ac44a421cafbf128c9462b8e9": [ // Multi-select checkboxes { "id": 1, "text": "Slack", "value": null, "required": true, "selected": true }, { "id": 2, "text": "Teams", "value": null, "required": false, "selected": false } ] }}Updating assignees with owners
Section titled “Updating assignees with owners”{ "owners": { "users": [1001, 1002], // Assign users 1001 and 1002 "groups": [], // Remove all group assignments "guests": ["new.client@example.com"] // Assign this guest }}Code samples
Section titled “Code samples”const accessToken = 'YOUR_PERSONAL_ACCESS_TOKEN';const orgId = 'YOUR_ORGANIZATION_ID';const runId = 'PROCESS_RUN_ID'; // Or null/omit for one-off taskconst taskId = 'TASK_ID_TO_UPDATE';
// Choose the correct URL based on task typeconst apiUrl = runId ? `https://go.tallyfy.com/api/organizations/${orgId}/runs/${runId}/tasks/${taskId}` : `https://go.tallyfy.com/api/organizations/${orgId}/tasks/${taskId}`;
const updatePayload = { // Example: Update deadline and a text form field deadline: "2025-07-01T09:00:00Z", // Use ISO 8601 Format taskdata: { "text_field_id_example": "Updated value from JS" // Use actual Field ID }, // Example: Change assignees (this REPLACES the entire list) owners: { users: [1005], // Assign only user 1005 groups: [], // Remove all group assignments guests: [] // Remove all guest assignments }};
const headers = new Headers();headers.append('Authorization', `Bearer ${accessToken}`);headers.append('Accept', 'application/json');headers.append('X-Tallyfy-Client', 'APIClient');headers.append('Content-Type', 'application/json');
fetch(apiUrl, { method: 'PUT', headers: headers, body: JSON.stringify(updatePayload)}).then(response => { return response.json().then(data => { // Attempt to parse JSON regardless of status if (!response.ok) { console.error(`Failed to update task ${taskId}:`, data); throw new Error(`HTTP error! status: ${response.status}`); } return data; // Pass successful data along });}).then(data => { console.log(`Successfully updated task ${taskId}:`); console.log(JSON.stringify(data, null, 2));}).catch(error => { console.error(`Error updating task ${taskId}:`, error.message);});import requestsimport jsonimport os
access_token = os.environ.get('TALLYFY_ACCESS_TOKEN', 'YOUR_PERSONAL_ACCESS_TOKEN')org_id = os.environ.get('TALLYFY_ORG_ID', 'YOUR_ORGANIZATION_ID')run_id = os.environ.get('TALLYFY_RUN_ID') # Get from env, might be None for one-off tasktask_id = 'TASK_ID_TO_UPDATE'
if run_id: api_url = f'https://go.tallyfy.com/api/organizations/{org_id}/runs/{run_id}/tasks/{task_id}'else: api_url = f'https://go.tallyfy.com/api/organizations/{org_id}/tasks/{task_id}'
headers = { 'Authorization': f'Bearer {access_token}', 'Accept': 'application/json', 'X-Tallyfy-Client': 'APIClient', 'Content-Type': 'application/json'}
# Note: Updating 'owners' replaces the entire list.# Fetch current task if you need to add/remove incrementally.update_payload = { 'summary': 'Task summary updated via Python.', # Example: Update a dropdown form field 'taskdata': { 'dropdown_field_id_example': { 'id': 3, # Option ID from template form field definition 'text': 'Selected Option C', 'value': None # Value is often null for dropdowns/radios } } # Add other fields like 'owners' or 'deadline' or 'title' as needed}
response = Nonetry: response = requests.put(api_url, headers=headers, json=update_payload) response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)
updated_task = response.json() print(f'Successfully updated task {task_id}:') print(json.dumps(updated_task, indent=4))
except requests.exceptions.HTTPError as http_err: error_details = "" try: if response is not None: error_details = response.json() except json.JSONDecodeError: if response is not None: error_details = response.text print(f"HTTP error occurred updating task {task_id}: {http_err}") print(f"Response Body: {error_details}")except requests.exceptions.RequestException as req_err: print(f"Request failed updating task {task_id}: {req_err}")except json.JSONDecodeError: print(f"Failed to decode successful JSON response for task update {task_id}") if response is not None: print(f"Response Text: {response.text}")except Exception as err: print(f"An unexpected error occurred: {err}")import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.io.IOException;import java.time.Duration;// Requires a JSON library like Jackson or Gson// import com.fasterxml.jackson.databind.ObjectMapper;// import java.util.Map;// import java.util.HashMap;// import java.util.List;
public class UpdateTask {
public static void main(String[] args) { String accessToken = System.getenv().getOrDefault("TALLYFY_ACCESS_TOKEN", "YOUR_PERSONAL_ACCESS_TOKEN"); String orgId = System.getenv().getOrDefault("TALLYFY_ORG_ID", "YOUR_ORGANIZATION_ID"); String runId = System.getenv("TALLYFY_RUN_ID"); // Set to null for one-off task String taskId = "TASK_ID_TO_UPDATE";
String apiUrl; if (runId != null && !runId.isEmpty()) { apiUrl = String.format("https://go.tallyfy.com/api/organizations/%s/runs/%s/tasks/%s", orgId, runId, taskId); } else { apiUrl = String.format("https://go.tallyfy.com/api/organizations/%s/tasks/%s", orgId, taskId); }
// --- Payload Construction --- // Using Jackson/Gson recommended: /* ObjectMapper mapper = new ObjectMapper(); Map<String, Object> updateData = new HashMap<>(); updateData.put("deadline", "2025-07-10T12:00:00Z"); Map<String, Object> taskData = new HashMap<>(); taskData.put("some_field_id", "new value"); updateData.put("taskdata", taskData); // Map<String, List<Integer>> owners = Map.of("users", List.of(1001)); // updateData.put("owners", owners); // Replaces assignees String jsonPayload; try { jsonPayload = mapper.writeValueAsString(updateData); } catch (Exception e) { System.err.println("Failed to serialize JSON: " + e.getMessage()); return; } */ // Simple manual JSON string: String jsonPayload = "{\"summary\": \"Updated via Java HttpClient\", \"taskdata\": {\"field_abc\":\"Java value\"}}"; // --- End Payload ---
HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build();
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(apiUrl)) .header("Authorization", "Bearer " + accessToken) .header("Accept", "application/json") .header("X-Tallyfy-Client", "APIClient") .header("Content-Type", "application/json") .PUT(HttpRequest.BodyPublishers.ofString(jsonPayload)) .build();
try { HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) { System.out.println("Successfully updated task " + taskId + ":"); System.out.println(response.body()); // TODO: Consider parsing JSON response } else { System.err.println("Failed to update task " + taskId + ". Status: " + response.statusCode()); System.err.println("Response Body: " + response.body()); } } catch (IOException | InterruptedException e) { System.err.println("Request failed: " + e.getMessage()); Thread.currentThread().interrupt(); } catch (Exception e) { System.err.println("An unexpected error occurred: " + e.getMessage()); e.printStackTrace(); } }}package main
import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" "os" "time")
func main() { accessToken := os.Getenv("TALLYFY_ACCESS_TOKEN") if accessToken == "" { accessToken = "YOUR_PERSONAL_ACCESS_TOKEN" } orgId := os.Getenv("TALLYFY_ORG_ID") if orgId == "" { orgId = "YOUR_ORGANIZATION_ID" } runId := os.Getenv("TALLYFY_RUN_ID") // Set to "" for one-off task taskId := "TASK_ID_TO_UPDATE"
var apiUrl string if runId != "" { apiUrl = fmt.Sprintf("https://go.tallyfy.com/api/organizations/%s/runs/%s/tasks/%s", orgId, runId, taskId) } else { apiUrl = fmt.Sprintf("https://go.tallyfy.com/api/organizations/%s/tasks/%s", orgId, taskId) }
// Note: Updating owners replaces the list updateData := map[string]interface{}{ "title": "Go Updated Task Title", "taskdata": map[string]interface{}{ // Update form field value "radio_button_field_id": "Option B", // Use actual Field ID }, // "owners": map[string][]interface{} { // Example: Update owners // "users": {1005}, // }, }
jsonData, err := json.Marshal(updateData) if err != nil { fmt.Printf("Error marshalling JSON: %v\n", err) return }
client := &http.Client{Timeout: 15 * time.Second} req, err := http.NewRequest(http.MethodPut, apiUrl, bytes.NewBuffer(jsonData)) if err != nil { fmt.Printf("Error creating update task request for task %s: %v\n", taskId, err) return }
req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("Accept", "application/json") req.Header.Set("X-Tallyfy-Client", "APIClient") req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req) if err != nil { fmt.Printf("Error executing update task request for task %s: %v\n", taskId, err) return } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf("Error reading update task response body for task %s: %v\n", taskId, err) return }
if resp.StatusCode != http.StatusOK { fmt.Printf("Failed to update task %s. Status: %d\nBody: %s\n", taskId, resp.StatusCode, string(body)) return }
fmt.Printf("Successfully updated task %s:\n", taskId) // Pretty print JSON response var prettyJSON bytes.Buffer if err := json.Indent(&prettyJSON, body, "", " "); err == nil { fmt.Println(prettyJSON.String()) } else { fmt.Println(string(body)) } // TODO: Unmarshal JSON if needed}#include <iostream>#include <string>#include <optional>#include <cpprest/http_client.h>#include <cpprest/json.h>
using namespace web;using namespace web::http;using namespace web::http::client;using namespace web::json;
pplx::task<void> UpdateTallyfyTask(const utility::string_t& taskId, const value& updatePayload, std::optional<utility::string_t> runId = std::nullopt){ utility::string_t accessToken = U("YOUR_PERSONAL_ACCESS_TOKEN"); utility::string_t orgId = U("YOUR_ORGANIZATION_ID");
utility::string_t apiUrlBase = U("https://go.tallyfy.com/api/organizations/") + orgId; utility::string_t apiUrl;
if (runId) { apiUrl = apiUrlBase + U("/runs/") + runId.value() + U("/tasks/") + taskId; } else { apiUrl = apiUrlBase + U("/tasks/") + taskId; }
http_client client(apiUrl); http_request request(methods::PUT);
request.headers().add(U("Authorization"), U("Bearer ") + accessToken); request.headers().add(U("Accept"), U("application/json")); request.headers().add(U("X-Tallyfy-Client"), U("APIClient")); request.headers().set_content_type(U("application/json")); request.set_body(updatePayload);
return client.request(request).then([taskId](http_response response) { utility::string_t taskIdW = taskId; return response.extract_json().then([response, taskIdW](pplx::task<value> task) { try { value const & body = task.get(); if (response.status_code() == status_codes::OK) { std::wcout << L"Successfully updated task " << taskIdW << L":\n" << body.serialize() << std::endl; } else { std::wcerr << L"Failed to update task " << taskIdW << L". Status: " << response.status_code() << L"\nResponse: " << body.serialize() << std::endl; } } catch (const http_exception& e) { std::wcerr << L"HTTP exception during update task: " << e.what() << std::endl; } catch (const std::exception& e) { std::wcerr << L"Exception during update task response handling: " << e.what() << std::endl; } }); });}
int main() { try { value payload = value::object(); payload[U("summary")] = value::string(U("C++ Updated Summary")); value taskdata = value::object(); taskdata[U("text_field_123")] = value::string(U("Value set by C++")); payload[U("taskdata")] = taskdata;
// Update a process task UpdateTallyfyTask(U("TASK_ID_TO_UPDATE"), payload, U("RUN_ID")).wait();
// Update a one-off task (runId omitted) // UpdateTallyfyTask(U("ONE_OFF_TASK_ID"), payload).wait();
} catch (const std::exception &e) { std::cerr << "Error in main: " << e.what() << std::endl; } return 0;}// Requires C++ REST SDK (Casablanca)using System;using System.Collections.Generic;using System.Net.Http;using System.Net.Http.Headers;using System.Text;using System.Text.Json;using System.Text.Json.Serialization; // For JsonIgnoreConditionusing System.Threading.Tasks;
public class TallyfyTaskUpdater{ private static readonly HttpClient client = new HttpClient();
// Payload class - define properties you might update public class TaskUpdatePayload { [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Title { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Summary { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Deadline { get; set; } // ISO 8601 string [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public TaskOwners Owners { get; set; } // Remember: Replaces existing [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public Dictionary<string, object> TaskData { get; set; } // Add other updatable fields as needed } public class TaskOwners { // Same as in Create One-Off Task example [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List<int> Users { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List<string> Guests { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List<string> Groups { get; set; } }
// Use runId = null for one-off tasks public static async Task UpdateTaskAsync(string taskId, TaskUpdatePayload payload, string runId = null) { var accessToken = Environment.GetEnvironmentVariable("TALLYFY_ACCESS_TOKEN") ?? "YOUR_PERSONAL_ACCESS_TOKEN"; var orgId = Environment.GetEnvironmentVariable("TALLYFY_ORG_ID") ?? "YOUR_ORGANIZATION_ID";
string apiUrl; if (!string.IsNullOrEmpty(runId)) { apiUrl = $"https://go.tallyfy.com/api/organizations/{orgId}/runs/{runId}/tasks/{taskId}"; } else { apiUrl = $"https://go.tallyfy.com/api/organizations/{orgId}/tasks/{taskId}"; }
try { using var request = new HttpRequestMessage(HttpMethod.Put, apiUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Headers.Add("X-Tallyfy-Client", "APIClient");
// Serialize payload, ignore nulls var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; string jsonPayload = JsonSerializer.Serialize(payload, options); request.Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.SendAsync(request); string responseBody = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode) // Expect 200 OK { Console.WriteLine($"Successfully updated task {taskId}:"); try { using var doc = JsonDocument.Parse(responseBody); Console.WriteLine(JsonSerializer.Serialize(doc.RootElement, new JsonSerializerOptions { WriteIndented = true })); } catch (JsonException) { Console.WriteLine(responseBody); } } else { Console.WriteLine($"Failed to update task {taskId}. Status: {response.StatusCode}"); Console.WriteLine($"Response: {responseBody}"); } } catch (HttpRequestException e) { Console.WriteLine($"Request Exception updating task {taskId}: {e.Message}"); } catch (JsonException jsonEx) { Console.WriteLine($"JSON Serialization Error: {jsonEx.Message}"); } catch (Exception ex) { Console.WriteLine($"An unexpected error occurred: {ex.Message}"); } }
// Example Usage: // static async Task Main(string[] args) // { // var taskUpdate = new TaskUpdatePayload { // Summary = "C# updated summary.", // TaskData = new Dictionary<string, object> { { "field_xyz", 123.45 } } // }; // // Update a process task // await UpdateTaskAsync("TASK_ID_1", taskUpdate, "RUN_ID_1"); // // Update a one-off task // // await UpdateTaskAsync("ONE_OFF_TASK_ID", taskUpdate); // }}Response
Section titled “Response”Returns 200 OK with the full task object after the update, wrapped in a data envelope.
{ "data": { "id": "TASK_ID_TO_UPDATE", "title": "Go Updated Task Title", "status": "active", "owners": { "users": [{ "id": 1005, ... }], "groups": [], "guests": [] }, "deadline": "2025-07-01T09:00:00Z", "started_at": "2025-06-01T09:00:00Z", "last_updated": "2025-05-20T16:00:00Z", "taskdata": { "text_field_id_example": "Updated value from JS", "dropdown_field_id_example": { "id": 3, ... }, "radio_button_field_id": "Option B" }, "webhook": null, "prevent_guest_comment": false, "position": 1, "is_oneoff_task": false }}Note that summary only appears in the response when you fetch a single task (not in list responses), or when you include ?with=summary.
Completed tasks can’t be updated - you’ll get a validation error. Other error codes: 404 (task not found), 403 (no permission), 422 (validation failure - wrong field type, missing required fields).
Related articles
Section titled “Related articles”Postman > Task operations and automation
Was this helpful?
- 2026 Tallyfy, Inc.
- Privacy Policy
- Terms of Use
- Report Issue
- Trademarks