GET List projects
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects
Returns a list of projects based on the provided workspace ID and filter params.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
Query
| name | type | required | description |
|---|
| member_only | boolean | false | Only projects where the caller has an active project role, directly or through a team; normal visibility and lifecycle filters still apply. |
| include_task_counts | boolean | false | Include permission-filtered task counts for this project page, including draft or completed projects returned by the project filters; no_project_task_count is returned on page 1. Off by default. |
| include_tasks | boolean | false | Include bounded picker previews of five task groups per project and five subtasks per group, with task_group_counts and child counts for pagination; no_project_tasks and no_project_task_group_counts are returned on page 1. Off by default. |
| unified_search | string | false | Unified picker search by project, client, task and subtask names before pagination. With include_tasks, projects matched by project or client name return all their tasks; other projects return only tasks and subtasks whose names match, with nonmatching parents included only as nonselectable context for matching subtasks. Overrides task_name for nested tasks; task_name still filters task counts. Literal case-insensitive substring. |
| include_picker_parent_group_counts | boolean | false | Include eligible unified-picker parent-task group counts for this project page; no_project_picker_parent_group_count is returned on page 1. Off by default. |
| include_picker_pinned_tasks | boolean | false | On page 1 without unified_search, return the current user's pinned tasks the unified picker offers as picker_pinned_tasks, sorted by name (at most 30). Off by default. |
| task_archived | boolean | false | Filter counted tasks by archived state; omit to include both. |
| task_recurring | boolean | false | Filter counted tasks by recurring state, matching the tasks endpoint. |
| task_state | []string | false | Filter counted tasks by state. |
| task_source | []string | false | Filter counted tasks by source, matching the tasks endpoint. |
| task_assignee_user_id | []integer | false | Count tasks assigned to these users, OR tasks assigned directly to task_assignee_team_id. |
| task_assignee_team_id | []integer | false | Count tasks assigned directly to these teams; does not expand team membership. |
| task_include_unassigned | boolean | false | Also count tasks or picker parent groups with no direct assignee and no live team assignment; combined with task_assignee_user_id/task_assignee_team_id as an OR for task counts. |
| task_name | string | false | Filter counted tasks by name independently of the project name filter; with include_tasks, search nested tasks by task, parent, project, or client name unless unified_search is supplied. unified_search overrides nested search only; task_name still filters task counts. |
| task_occurrence_window_date | string | false | Repeats of a recurring task dated after this date + task_occurrence_window_days are excluded from task counts, picker previews and unified task search; earlier ones remain. Default: today (UTC). |
| task_occurrence_window_days | integer | false | Days after task_occurrence_window_date, 0–31. Default: 7. |
| page | integer | false | page number |
| per_page | integer | false | results per page |
| order_by | []string | false | order by. Also accepts cf_<id> / -cf_<id> to sort by any active workspace custom field. Multi_select and users CF types sort by their canonicalized (sorted) value array, so projects sharing the same set cluster together. |
| pinned | boolean | false | filter by only pinned tasks |
| archived | boolean | false | filter by archived state (true = archived only, false = active only, omit = active only, empty = all projects) |
| completed | boolean | false | filter by completion state (true = completed only, false = non-completed only, empty = all projects, omit = non-completed only, or all projects when archived=true) |
| private | boolean | false | filter by project privacy (true for private, false for public) |
| name | string | false | filter by project name or client name |
| client_id | []integer | false | filter by client IDs |
| creator_id | []integer | false | filter by project creator id |
| tag_id | []integer | false | filter by tag IDs |
| project_id | []integer | false | filter by project IDs |
| user_id | []integer | false | return only projects accessible by the given users (requires manage workspace users when inspecting another user). Incompatible with only_me. |
| only_me | boolean | false | return public projects union projects the current user is a member of (Track-shaped timer/picker scope; suppresses admin view_private_projects full-access and locked-private upsell during access resolution; still honors view_public_projects). Incompatible with user_id. |
| include_rates | boolean | false | includes the projects' rate data |
| include_rollover | boolean | false | computes and returns rollover_mins on each recurring instance (off by default — opt in only when the FE displays rollover, since per-chain hydration costs an extra OLTP + 2 warehouse queries) |
| include_idle_recurring_templates | boolean | false | surface recurring templates (rrule != null) that have no live, uncompleted instance — i.e. either never materialized or every prior instance is already completed. Off by default. Useful for letting the user start the next period after dropping auto-first-instance materialization. |
| collapse_recurring | boolean | false | series-shaped listing. A series appears as its template whenever the template matches the listing; instances matching filters their template does not (access, name, completed, ...) appear individually. Supersedes include_idle_recurring_templates while set. Aggregations on a template row describe the template alone (its blueprint tasks, no tracked time), not the series. |
| include_drafts | boolean | false | include draft projects in the response (default false hides them; requires view_draft_projects permission) |
| include_locked_private | boolean | false | include the workspace's private projects read-only for role-entitled users whose plan lacks the private-projects feature (upsell flow). Their activity figures are blurred to zero. Off by default; other consumers never see private projects they can't otherwise access. |
| start_date | string | false | filter projects overlapping date range (start). Used with end_date to find projects where project.start_date <= end_date AND project.end_date >= start_date |
| end_date | string | false | filter projects overlapping date range (end). Used with start_date to find projects where project.start_date <= end_date AND project.end_date >= start_date |
| date_overlap_start | string | false | [LEGACY] use start_date instead |
| date_overlap_end | string | false | [LEGACY] use end_date instead |
| cf_filter | []string | false | filter by custom field values (format: fieldID:value1,value2) |
Response
200
| Name | Type | Description |
|---|
| data | Array of object | - |
| no_project_picker_parent_group_count | integer | - |
| no_project_task_count | integer | - |
| no_project_task_group_counts | object | - |
| no_project_tasks | Array of object | - |
| page | integer | - |
| per_page | integer | - |
| picker_pinned_tasks | Array of object | - |
| total | integer | - |
data
| Name | Type | Description |
|---|
| active | boolean | - |
| alert_status | object | - |
| archived_at | string | - |
| auto_compute_estimates | boolean | Deprecated by estimate_source. True mirrors a computed source: "tasks" or "designation". |
| billable | boolean | - |
| client | object | - |
| client_id | integer | - |
| color | string | - |
| completed_at | string | - |
| completion_mode | string | Valid values: manual, automatic. |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| designation_estimated_mins | integer | - |
| draft | boolean | - |
| end_date | string | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| estimated_mins | integer | - |
| filtered_task_count | integer | - |
| fixed_fee | object | - |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| parent_project_id | integer | - |
| permissions | Array of string | - |
| picker_parent_group_count | integer | - |
| pinned | boolean | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | - |
| rollover_mins | integer | null |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | - |
| source_template_id | integer | - |
| start_date | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| task_estimated_mins | integer | - |
| task_group_counts | object | - |
| tasks | Array of object | - |
| toggl_user_id | integer | - |
| total_tasks | integer | - |
| total_tracked_secs | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
alert_status
| Name | Type | Description |
|---|
| estimate_used_pct | number | - |
| has_active_alerts | boolean | - |
| highest_triggered_threshold | integer | - |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
task_group_counts
| Name | Type | Description |
|---|
| eligible_total | integer | - |
| matching_total | integer | - |
tasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| eligible_child_count | integer | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| group_id | integer | GroupID stays stable when a hidden parent is represented by an eligible child. |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| matching_child_count | integer | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| parent_visible | boolean | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| selectable | boolean | Selectable is false for ineligible parents and nonmatching context parents under unified_search. |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| subtasks | Array of object | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
subtasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
no_project_task_group_counts
| Name | Type | Description |
|---|
| eligible_total | integer | - |
| matching_total | integer | - |
no_project_tasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| eligible_child_count | integer | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| group_id | integer | GroupID stays stable when a hidden parent is represented by an eligible child. |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| matching_child_count | integer | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| parent_visible | boolean | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| selectable | boolean | Selectable is false for ineligible parents and nonmatching context parents under unified_search. |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| subtasks | Array of object | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
subtasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
picker_pinned_tasks
| Name | Type | Description |
|---|
| parent | object | - |
| project | object | - |
| task | object | - |
parent
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
project
| Name | Type | Description |
|---|
| client | object | - |
| color | string | - |
| end_date | string | - |
| id | integer | - |
| name | string | - |
| pinned | boolean | - |
| recurring_project_id | integer | - |
| start_date | string | - |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
task
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
400
Invalid request
500
Internal Server Error
POST Create a new project
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects
Creates a new project with the provided name, workspace ID, parent project ID, and client ID. Omitted private inherits the parent project visibility, or the workspace default when there is no parent. Explicit values retain normal authorization.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X POST https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects \
-H "Content-Type: application/json" \
-d '\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}' \
-u <email>:<password>
bytes, err := json.Marshal('\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPost,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = "application/json"
req.body = \{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}.to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects", {
method: "POST",
body: \{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\},
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.post('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects', json=\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}, headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::POST, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects".to_string())
.json(&serde_json::json!(\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
Body
| Name | Type | Description |
|---|
| auto_compute_estimates | boolean | Deprecated by estimate_source. Sets it to "tasks" if true. |
| billable | boolean | - |
| client_id | integer | - |
| color | string | - |
| completion_mode | string | Valid values: manual, automatic. |
| custom_fields | object | - |
| description | string | - |
| draft | boolean | - |
| end_date | string | - |
| estimate_source | string | null |
| estimated_mins | integer | - |
| fixed_fee | object | - |
| is_template | boolean | - |
| name | string | - |
| parent_project_id | integer | - |
| pinned | boolean | - |
| private | boolean | - |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | - |
| start_date | string | - |
| tag_ids | Array of integer | - |
custom_fields
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
Response
201
Project created successfully
400
Invalid project parameters
500
Internal Server Error
GET Get a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}
Returns a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id} \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
200
| Name | Type | Description |
|---|
| active | boolean | - |
| alert_status | object | - |
| archived_at | string | - |
| auto_compute_estimates | boolean | Deprecated by estimate_source. True mirrors a computed source: "tasks" or "designation". |
| billable | boolean | - |
| client | object | - |
| client_id | integer | - |
| color | string | - |
| completed_at | string | - |
| completion_mode | string | Valid values: manual, automatic. |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| designation_estimated_mins | integer | - |
| draft | boolean | - |
| end_date | string | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| estimated_mins | integer | - |
| filtered_task_count | integer | - |
| fixed_fee | object | - |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| parent_project_id | integer | - |
| permissions | Array of string | - |
| picker_parent_group_count | integer | - |
| pinned | boolean | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | - |
| rollover_mins | integer | null |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | - |
| source_template_id | integer | - |
| start_date | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| task_estimated_mins | integer | - |
| task_group_counts | object | - |
| tasks | Array of object | - |
| toggl_user_id | integer | - |
| total_tasks | integer | - |
| total_tracked_secs | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
alert_status
| Name | Type | Description |
|---|
| estimate_used_pct | number | - |
| has_active_alerts | boolean | - |
| highest_triggered_threshold | integer | - |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
task_group_counts
| Name | Type | Description |
|---|
| eligible_total | integer | - |
| matching_total | integer | - |
tasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| eligible_child_count | integer | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| group_id | integer | GroupID stays stable when a hidden parent is represented by an eligible child. |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| matching_child_count | integer | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| parent_visible | boolean | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| selectable | boolean | Selectable is false for ineligible parents and nonmatching context parents under unified_search. |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| subtasks | Array of object | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
subtasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
400
Invalid request
404
Project does not exist
500
Internal Server Error
PUT Update project
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}
Update an existing project
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PUT https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id} \
-H "Content-Type: application/json" \
-d '\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}' \
-u <email>:<password>
bytes, err := json.Marshal('\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}')
req = Net::HTTP::Put.new(uri)
req['Content-Type'] = "application/json"
req.body = \{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}.to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}", {
method: "PUT",
body: \{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\},
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.put('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}', json=\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}, headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PUT, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}".to_string())
.json(&serde_json::json!(\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"is_template":"boolean","name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | Project ID |
Body
| Name | Type | Description |
|---|
| auto_compute_estimates | boolean | Deprecated by estimate_source. Sets it to "tasks" if true. |
| billable | boolean | - |
| client_id | integer | - |
| color | string | - |
| completion_mode | string | Valid values: manual, automatic. |
| custom_fields | object | - |
| description | string | - |
| draft | boolean | - |
| end_date | string | - |
| estimate_source | string | null |
| estimated_mins | integer | - |
| fixed_fee | object | - |
| is_template | boolean | - |
| name | string | - |
| parent_project_id | integer | - |
| pinned | boolean | - |
| private | boolean | - |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | - |
| start_date | string | - |
| tag_ids | Array of integer | - |
custom_fields
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
DELETE Delete a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}
Deletes a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X DELETE https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id} \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}')
req = Net::HTTP::Delete.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.delete('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::DELETE, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
PATCH Patch project
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}
Partially update an existing project
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PATCH https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id} \
-H "Content-Type: application/json" \
-d '\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}' \
-u <email>:<password>
bytes, err := json.Marshal('\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}')
req = Net::HTTP::Patch.new(uri)
req['Content-Type'] = "application/json"
req.body = \{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}.to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}", {
method: "PATCH",
body: \{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\},
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.patch('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}', json=\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}, headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PATCH, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}".to_string())
.json(&serde_json::json!(\{"auto_compute_estimates":"boolean","billable":"boolean","client_id":"integer","color":"string","completion_mode":"string","custom_fields":\{\},"description":"string","draft":"boolean","end_date":"string","estimate_source":"string","estimated_mins":"integer","fixed_fee":\{"amount":"number","currency":"string"\},"name":"string","parent_project_id":"integer","pinned":"boolean","private":"boolean","rollover_mode":"string","rrule":"string","start_date":"string","tag_ids":[\{\}]\}))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | Project ID |
Body
| Name | Type | Description |
|---|
| auto_compute_estimates | boolean | null |
| billable | boolean | - |
| client_id | integer | null |
| color | string | null |
| completion_mode | string | Valid values: manual, automatic. |
| custom_fields | object | - |
| description | string | null |
| draft | boolean | - |
| end_date | string | null |
| estimate_source | string | Valid values: manual, tasks, designation. |
| estimated_mins | integer | null |
| fixed_fee | object | - |
| name | string | - |
| parent_project_id | integer | null |
| pinned | boolean | - |
| private | boolean | - |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | null |
| start_date | string | null |
| tag_ids | Array of integer | - |
custom_fields
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
PATCH Archives a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive
Archives a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PATCH https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive')
req = Net::HTTP::Patch.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.patch('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PATCH, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/archive".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
GET Get a project with its children sub-projects by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children
Returns a project and its children sub-projects by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/children".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Query
| name | type | required | description |
|---|
| page | integer | false | page number |
| per_page | integer | false | results per page |
| order_by | []string | false | order by |
Response
200
| Name | Type | Description |
|---|
| data | Array of object | - |
| page | integer | - |
| per_page | integer | - |
data
| Name | Type | Description |
|---|
| active | boolean | - |
| alert_status | object | - |
| archived_at | string | - |
| auto_compute_estimates | boolean | Deprecated by estimate_source. True mirrors a computed source: "tasks" or "designation". |
| billable | boolean | - |
| client | object | - |
| client_id | integer | - |
| color | string | - |
| completed_at | string | - |
| completion_mode | string | Valid values: manual, automatic. |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| designation_estimated_mins | integer | - |
| draft | boolean | - |
| end_date | string | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| estimated_mins | integer | - |
| filtered_task_count | integer | - |
| fixed_fee | object | - |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| parent_project_id | integer | - |
| permissions | Array of string | - |
| picker_parent_group_count | integer | - |
| pinned | boolean | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | - |
| rollover_mins | integer | null |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | - |
| source_template_id | integer | - |
| start_date | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| task_estimated_mins | integer | - |
| task_group_counts | object | - |
| tasks | Array of object | - |
| toggl_user_id | integer | - |
| total_tasks | integer | - |
| total_tracked_secs | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
alert_status
| Name | Type | Description |
|---|
| estimate_used_pct | number | - |
| has_active_alerts | boolean | - |
| highest_triggered_threshold | integer | - |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
task_group_counts
| Name | Type | Description |
|---|
| eligible_total | integer | - |
| matching_total | integer | - |
tasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| eligible_child_count | integer | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| group_id | integer | GroupID stays stable when a hidden parent is represented by an eligible child. |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| matching_child_count | integer | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| parent_visible | boolean | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| selectable | boolean | Selectable is false for ineligible parents and nonmatching context parents under unified_search. |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| subtasks | Array of object | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
last_integration_dates
| Name | Type | Description |
|---|
| end | string | - |
| start | string | - |
project_assignment
| Name | Type | Description |
|---|
| accuracy | number | - |
| confirmed_at | string | - |
| match_tier | string | Valid values: exact_name, similar_name. |
| matched_name | string | - |
| normalized_name | string | - |
| origin | string | Valid values: manual, auto_suggestion, confirmed_suggestion, integration, legacy, explicit_mapping. |
| suggested_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
subtasks
| Name | Type | Description |
|---|
| allocation_unit | string | Valid values: percent, flat. |
| archived_at | string | - |
| assignee_user_ids | Array of integer | - |
| assignees | Array of object | A unified column for all task entity assignments |
| auto_log_time | boolean | - |
| billable | boolean | null |
| client | object | - |
| color | string | - |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| end_date | string | - |
| estimate_type | string | Valid values: daily, total. |
| estimated_mins | integer | - |
| id | integer | - |
| is_recurring_series | boolean | IsRecurringSeries marks a canonical series root (S). Server-owned and read-only: no current API path can set it, and the response only exposes the marker while series behavior stays disabled. |
| is_template | boolean | - |
| metadata | object | - |
| name | string | - |
| notes | string | - |
| parent_task_id | integer | - |
| parent_task_name | string | - |
| pinned | boolean | - |
| position | integer | - |
| priority | string | Valid values: none, low, medium, high. |
| priority_at | string | - |
| private | boolean | - |
| project | object | - |
| project_id | integer | - |
| recurrence_date | string | - |
| recurring_rule | string | The rule of the task's series (RRULE with DTSTART); omitted for a normal task and once the series has stopped. |
| recurring_series_id | integer | The series this task is an occurrence of; omitted for a normal task. Only the server sets it. |
| recurring_task_id | integer | - |
| rollup_enabled | boolean | - |
| rrule | string | - |
| source | string | - |
| source_template_task_id | integer | - |
| start_date | string | - |
| status | object | - |
| status_id | integer | - |
| status_updated_at | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
assignees
| Name | Type | Description |
|---|
| id | integer | - |
| type | string | Valid values: user, team. |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
| Name | Type | Description |
|---|
| all_day | boolean | - |
| calendar_event_id | integer | - |
| calendar_id | integer | - |
| event_classification | string | EventClassification is the calendar provider's own classification of the event behind this task, normalised by the calendar service — see calmodels.EventClassification for the values. Absent when the provider reported no classification. |
| extension_source | string | Browser-extension provenance: the source/config that produced the task and the page URL it was tracked from. Written by the extension's start-from-description flow; ExtensionURL is queryable via FindByURL. |
| extension_url | string | - |
| external_id | string | - |
| ical_uid | string | - |
| last_asserted_track_project_id | integer | LastAssertedTrackProjectID is the Track planned_task.project_id that the Focus→Track mirror last successfully wrote for this task. Track→Focus uses it to distinguish a stale echo (Track still holds this value after a Focus-side project move) from an intentional Track-side project move. Internal mirror state, written by toggl_api focus_sync_worker; not user-facing. |
| last_integration_dates | object | LastIntegrationDates are the start and end dates the task's integration last sent. Integration sync overwrites the task's dates only when the source's dates differ from these, so dates set in Focus survive unrelated source edits. Internal sync state; not user-facing. |
| meeting_link | string | - |
| project_assignment | object | - |
| updated_at | string | - |
project
| Name | Type | Description |
|---|
| archived_at | string | - |
| billable | boolean | - |
| client | object | - |
| color | string | - |
| custom_field_values | Array of object | CustomFieldValues are the parent project's CF values, hydrated by callers that surface them (currently the task list, via task.service.hydrateTaskProjectCustomFieldValues which routes through customfield.Service.GetFieldsByIDs and respects the PermissionViewWorkspaceProjectCustomFields gate). Producers that don't hydrate (e.g. timeentry) leave the slice empty; omitempty hides it on those responses. |
| draft | boolean | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| permissions | Array of string | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | RecurringProjectID links an instance to its recurring template, so clients can lane an entry under a collapsed series. |
status
| Name | Type | Description |
|---|
| emoji | string | - |
| id | integer | - |
| name | string | - |
| type | string | Valid values: todo, done, in_progress, blocked. |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
400
Invalid request
404
Project does not exist
500
Internal Server Error
GET List project memmbers
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members
Returns a list of userIDs and groupIDs that are part of the given project.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
200
List of project members
| Name | Type | Description |
|---|
| group_ids | Array of object | - |
| project_id | integer | - |
| user_ids | Array of object | - |
group_ids
| Name | Type | Description |
|---|
| group_id | integer | - |
| manager | boolean | null |
| role_id | integer | - |
user_ids
| Name | Type | Description |
|---|
| manager | boolean | - |
| user_id | integer | - |
400
Invalid request
403
Forbidden
404
Project not found
500
Internal Server Error
PUT Update project member role
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members
Updates the role of a project member (user or group).
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PUT https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members \
-H "Content-Type: application/json" \
-d '\{"group_id":"integer","role_id":"integer","user_id":"integer"\}' \
-u <email>:<password>
bytes, err := json.Marshal('\{"group_id":"integer","role_id":"integer","user_id":"integer"\}')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members')
req = Net::HTTP::Put.new(uri)
req['Content-Type'] = "application/json"
req.body = \{"group_id":"integer","role_id":"integer","user_id":"integer"\}.to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", {
method: "PUT",
body: \{"group_id":"integer","role_id":"integer","user_id":"integer"\},
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.put('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members', json=\{"group_id":"integer","role_id":"integer","user_id":"integer"\}, headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PUT, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members".to_string())
.json(&serde_json::json!(\{"group_id":"integer","role_id":"integer","user_id":"integer"\}))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Body
| Name | Type | Description |
|---|
| group_id | integer | - |
| role_id | integer | - |
| user_id | integer | - |
Response
204
No Content
400
Invalid request
403
Forbidden
404
Project not found
500
Internal Server Error
POST Add project members
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members
Adds users and groups to the given project.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X POST https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members \
-H "Content-Type: application/json" \
-d '\{"group_ids":[\{\}],"role_id":"integer","user_ids":[\{\}]\}' \
-u <email>:<password>
bytes, err := json.Marshal('\{"group_ids":[\{\}],"role_id":"integer","user_ids":[\{\}]\}')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPost,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = "application/json"
req.body = \{"group_ids":[\{\}],"role_id":"integer","user_ids":[\{\}]\}.to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", {
method: "POST",
body: \{"group_ids":[\{\}],"role_id":"integer","user_ids":[\{\}]\},
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.post('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members', json=\{"group_ids":[\{\}],"role_id":"integer","user_ids":[\{\}]\}, headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::POST, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members".to_string())
.json(&serde_json::json!(\{"group_ids":[\{\}],"role_id":"integer","user_ids":[\{\}]\}))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Body
| Name | Type | Description |
|---|
| group_ids | Array of integer | - |
| role_id | integer | - |
| user_ids | Array of integer | - |
Response
204
No Content
400
Invalid request
403
Forbidden
404
Project not found
500
Internal Server Error
DELETE Remove project member
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members
Removes a single user or group from the given project.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X DELETE https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members \
-H "Content-Type: application/json" \
-d '\{"group_id":"integer","user_id":"integer"\}' \
-u <email>:<password>
bytes, err := json.Marshal('\{"group_id":"integer","user_id":"integer"\}')
if err != nil {
print(err)
}
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", bytes.NewBuffer(bytes))
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members')
req = Net::HTTP::Delete.new(uri)
req['Content-Type'] = "application/json"
req.body = \{"group_id":"integer","user_id":"integer"\}.to_json
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members", {
method: "DELETE",
body: \{"group_id":"integer","user_id":"integer"\},
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.delete('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members', json=\{"group_id":"integer","user_id":"integer"\}, headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::DELETE, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/members".to_string())
.json(&serde_json::json!(\{"group_id":"integer","user_id":"integer"\}))
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Body
| Name | Type | Description |
|---|
| group_id | integer | - |
| user_id | integer | - |
Response
204
No Content
400
Invalid request
403
Forbidden
404
Project not found
500
Internal Server Error
GET Get a project with its parent projects by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents
Returns a project and its parent projects by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents')
req = Net::HTTP::Get.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.get('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::GET, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/parents".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Query
| name | type | required | description |
|---|
| page | integer | false | page number |
| per_page | integer | false | results per page |
| order_by | []string | false | order by |
Response
200
| Name | Type | Description |
|---|
| data | Array of object | - |
| page | integer | - |
| per_page | integer | - |
data
| Name | Type | Description |
|---|
| active | boolean | - |
| archived_at | string | - |
| auto_compute_estimates | boolean | Deprecated by estimate_source. True mirrors a computed source: "tasks" or "designation". |
| billable | boolean | - |
| client | object | - |
| client_id | integer | - |
| color | string | - |
| completed_at | string | - |
| completion_mode | string | Valid values: manual, automatic. |
| created_at | string | - |
| custom_field_values | Array of object | - |
| deleted_at | string | - |
| description | string | - |
| draft | boolean | - |
| end_date | string | - |
| estimate_source | string | Valid values: manual, tasks, designation. |
| estimated_mins | integer | - |
| fixed_fee | object | - |
| id | integer | - |
| is_template | boolean | - |
| name | string | - |
| parent_project_id | integer | - |
| permissions | Array of string | - |
| pinned | boolean | - |
| private | boolean | - |
| rate | object | - |
| recurring_project_id | integer | - |
| rollover_mode | string | Valid values: expire, carry_all, carry_over. |
| rrule | string | - |
| source_template_id | integer | - |
| start_date | string | - |
| tag_ids | Array of integer | - |
| tags | Array of object | - |
| toggl_user_id | integer | - |
| updated_at | string | - |
| workspace_id | integer | - |
client
| Name | Type | Description |
|---|
| active | boolean | - |
| id | integer | - |
| name | string | - |
custom_field_values
| Name | Type | Description |
|---|
| custom_field_id | integer | - |
| custom_field_name | string | - |
| field_type | string | - |
| selected_options | Array of object | - |
| value | object | - |
selected_options
| Name | Type | Description |
|---|
| is_deleted | boolean | - |
| option_id | integer | - |
| option_name | string | - |
fixed_fee
| Name | Type | Description |
|---|
| amount | number | - |
| currency | string | - |
rate
| Name | Type | Description |
|---|
| billable | boolean | - |
| currency | string | - |
| end_at | string | - |
| has_more_rates | boolean | - |
| hourly_rate | number | - |
| project_color | string | - |
| project_created_at | string | - |
| project_id | integer | - |
| project_name | string | - |
| project_rate_id | integer | - |
| start_at | string | - |
| workspace_rate_id | integer | - |
| Name | Type | Description |
|---|
| color | string | - |
| id | integer | - |
| name | string | - |
400
Invalid request
404
Project does not exist
500
Internal Server Error
POST Pin a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned
Pins a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X POST https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodPost,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.post('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::POST, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
DELETE Unpin a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned
Unpins a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X DELETE https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodPut,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned')
req = Net::HTTP::Delete.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.delete('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::DELETE, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/pinned".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
PATCH Restore a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore
Restores a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PATCH https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore')
req = Net::HTTP::Patch.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.patch('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PATCH, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/restore".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error
PATCH Unarchive a project by ID
https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive
Unarchives a project by the provided ID.
- cURL
- Go
- Ruby
- JavaScript
- Python
- Rust
curl -X PATCH https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive \
-H "Content-Type: application/json" \
-u <email>:<password>
req, err := http.NewRequest(http.MethodGet,
"https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive")
if err != nil {
print(err)
}
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.SetBasicAuth("<email>", "<password>")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
print(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
print(err)
}
fmt.Print(string(body))
require 'net/http'
require 'uri'
require 'json'
uri = URI('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive')
req = Net::HTTP::Patch.new(uri)
req['Content-Type'] = "application/json"
req.basic_auth '<email>', '<password>'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts JSON.parse(res.body)
fetch("https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64.encode(<email>:<password>)}`
},
})
.then((resp) => resp.json())
.then((json) => {
console.log(json);
})
.catch(err => console.error(err));
import requests
from base64 import b64encode
data = requests.patch('https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive', headers={'content-type': 'application/json', 'Authorization' : 'Basic %s' % b64encode(b"<email>:<password>").decode("ascii")})
print(data.json())
extern crate tokio;
extern crate serde_json;
use reqwest::{Client};
use reqwest::header::{CONTENT_TYPE};
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new().basic_auth("<email>", "<password>");
let json = client.request(Method::PATCH, "https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/projects/{project_id}/unarchive".to_string())
.header(CONTENT_TYPE, "application/json")
.send()
.await?
.json()
.await?;
println!("{:#?}", json);
Ok(())
}
Parameters
Path
| name | type | required | description |
|---|
| organization_id | integer | true | organization ID |
| workspace_id | integer | true | workspace ID |
| project_id | integer | true | project ID |
Response
204
No Content
400
Invalid request
404
Project does not exist
409
The project or its tasks changed at the same time, try again (error=project_changed_concurrently)
500
Internal Server Error