Toggl Track
Access the Toggl Track API with managed OAuth authentication. Track time, manage projects, clients, tags, and workspaces.
Quick Start
# Get current user info
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/toggl-track/api/v9/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/toggl-track/{native-api-path}
Maton proxies requests to api.track.toggl.com and automatically injects your credentials.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Toggl Track OAuth connections at https://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=toggl-track&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'toggl-track'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-13T19:31:31.452264Z",
"last_updated_time": "2026-02-13T19:36:10.489069Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "toggl-track",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple Toggl Track connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/toggl-track/api/v9/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
Security & Permissions
- Access is scoped to time entries, projects, clients, workspaces, and tags within the connected Toggl Track account.
- All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.
API Reference
User & Workspace
Get Current User
GET /toggl-track/api/v9/me
Response:
{
"id": 12932942,
"email": "user@example.com",
"fullname": "John Doe",
"timezone": "America/Los_Angeles",
"default_workspace_id": 21180405,
"beginning_of_week": 1,
"image_url": "https://assets.track.toggl.com/images/profile.png"
}
List Workspaces
GET /toggl-track/api/v9/me/workspaces
Get Workspace
GET /toggl-track/api/v9/workspaces/{workspace_id}
List Workspace Users
GET /toggl-track/api/v9/workspaces/{workspace_id}/users
Time Entries
List Time Entries
GET /toggl-track/api/v9/me/time_entries
Query Parameters:
since(integer) - UNIX timestamp for entries modified after this timebefore(string) - Get entries before this date (RFC3339 or YYYY-MM-DD)start_date(string) - Filter start date (YYYY-MM-DD)end_date(string) - Filter end date (YYYY-MM-DD)
Get Current (Running) Time Entry
GET /toggl-track/api/v9/me/time_entries/current
Returns null if no time entry is currently running.
Get Time Entry by ID
GET /toggl-track/api/v9/me/time_entries/{time_entry_id}
Create Time Entry
POST /toggl-track/api/v9/workspaces/{workspace_id}/time_entries
Content-Type: application/json
{
"description": "Working on project",
"start": "2026-02-13T10:00:00Z",
"duration": -1,
"workspace_id": 21180405,
"project_id": 216896134,
"tag_ids": [20053808],
"created_with": "maton-api"
}
Note: Set duration to -1 to start a running timer. The created_with field is required.
Response:
{
"id": 4290254971,
"workspace_id": 21180405,
"project_id": null,
"task_id": null,
"billable": false,
"start": "2026-02-13T19:58:43Z",
"stop": null,
"duration": -1,
"description": "Working on project",
"tags": null,
"tag_ids": null,
"user_id": 12932942
}
Update Time Entry
PUT /toggl-track/api/v9/workspaces/{workspace_id}/time_entries/{time_entry_id}
Content-Type: application/json
{
"description": "Updated description",
"project_id": 216896134
}
Stop Running Time Entry
PATCH /toggl-track/api/v9/workspaces/{workspace_id}/time_entries/{time_entry_id}/stop
Delete Time Entry
DELETE /toggl-track/api/v9/workspaces/{workspace_id}/time_entries/{time_entry_id}
Projects
List Projects
GET /toggl-track/api/v9/workspaces/{workspace_id}/projects
Query Parameters:
active(boolean) - Filter by active statussince(integer) - UNIX timestamp for modification filtername(string) - Filter by project namepage(integer) - Page numberper_page(integer) - Items per page (max 200)
Get Project
GET /toggl-track/api/v9/workspaces/{workspace_id}/projects/{project_id}
Create Project
POST /toggl-track/api/v9/workspaces/{workspace_id}/projects
Content-Type: application/json
{
"name": "New Project",
"active": true,
"is_private": true,
"client_id": 68493239,
"color": "#0b83d9",
"billable": true
}
Response:
{
"id": 216896134,
"workspace_id": 21180405,
"client_id": null,
"name": "New Project",
"is_private": true,
"active": true,
"color": "#0b83d9",
"billable": true,
"created_at": "2026-02-13T19:58:36+00:00"
}
Update Project
PUT /toggl-track/api/v9/workspaces/{workspace_id}/projects/{project_id}
Content-Type: application/json
{
"name": "Updated Project Name",
"color": "#ff0000"
}
Delete Project
DELETE /toggl-track/api/v9/workspaces/{workspace_id}/projects/{project_id}
Clients
List Clients
GET /toggl-track/api/v9/workspaces/{workspace_id}/clients
Query Parameters:
status(string) - Filter:active,archived, orbothname(string) - Case-insensitive name filter
Get Client
GET /toggl-track/api/v9/workspaces/{workspace_id}/clients/{client_id}
Create Client
POST /toggl-track/api/v9/workspaces/{workspace_id}/clients
Content-Type: application/json
{
"name": "New Client",
"notes": "Client notes here"
}
Response:
{
"id": 68493239,
"wid": 21180405,
"archived": false,
"name": "New Client",
"at": "2026-02-13T19:58:36+00:00",
"creator_id": 12932942
}
Update Client
PUT /toggl-track/api/v9/workspaces/{workspace_id}/clients/{client_id}
Content-Type: application/json
{
"name": "Updated Client Name"
}
Delete Client
DELETE /toggl-track/api/v9/workspaces/{workspace_id}/clients/{client_id}
Archive Client
POST /toggl-track/api/v9/workspaces/{workspace_id}/clients/{client_id}/archive
Restore Client
POST /toggl-track/api/v9/workspaces/{workspace_id}/clients/{client_id}/restore
Content-Type: application/json
{
"restore_all_projects": true
}
Tags
List Tags
GET /toggl-track/api/v9/workspaces/{workspace_id}/tags
Query Parameters:
page(integer) - Page numberper_page(integer) - Items per page
Create Tag
POST /toggl-track/api/v9/workspaces/{workspace_id}/tags
Content-Type: application/json
{
"name": "New Tag"
}
Response:
{
"id": 20053808,
"workspace_id": 21180405,
"name": "New Tag",
"at": "2026-02-13T19:58:37.115714Z",
"creator_id": 12932942
}
Update Tag
PUT /toggl-track/api/v9/workspaces/{workspace_id}/tags/{tag_id}
Content-Type: application/json
{
"name": "Updated Tag Name"
}
Delete Tag
DELETE /toggl-track/api/v9/workspaces/{workspace_id}/tags/{tag_id}
Pagination
Toggl Track uses page-based pagination for most list endpoints:
GET /toggl-track/api/v9/workspaces/{workspace_id}/projects?page=1&per_page=50
For time entries, use timestamp-based filtering:
GET /toggl-track/api/v9/me/time_entries?since=1707840000&start_date=2026-02-01&end_date=2026-02-28
Code Examples
JavaScript
const response = await fetch(
'https://api.maton.ai/toggl-track/api/v9/me/time_entries',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const timeEntries = await response.json();
Python
import os
import requests
response = requests.get(
'https://api.maton.ai/toggl-track/api/v9/me/time_entries',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
time_entries = response.json()
Start a Timer
import os
import requests
from datetime import datetime, timezone
response = requests.post(
'https://api.maton.ai/toggl-track/api/v9/workspaces/21180405/time_entries',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'description': 'Working on task',
'start': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
'duration': -1,
'workspace_id': 21180405,
'created_with': 'maton-api'
}
)
Notes
- Workspace IDs are integers (e.g.,
21180405) - Time entry IDs are large integers (e.g.,
4290254971) - Duration is in seconds; use
-1for running timers - Timestamps use ISO 8601 format (e.g.,
2026-02-13T19:58:43Z) - The
created_withfield is required when creating time entries - IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing Toggl Track connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 403 | Access denied |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Toggl Track API |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
toggl-track. For example:
- Correct:
https://api.maton.ai/toggl-track/api/v9/me - Incorrect:
https://api.maton.ai/api/v9/me