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://gateway.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://gateway.maton.ai/toggl-track/{native-api-path}
Replace {native-api-path} with the actual Toggl Track API endpoint path. The gateway 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://ctrl.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.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://ctrl.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://ctrl.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": "0acc2145-4d3e-4eaf-bdfd-7b04e0e0d649",
"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://ctrl.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://gateway.maton.ai/toggl-track/api/v9/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '0acc2145-4d3e-4eaf-bdfd-7b04e0e0d649')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If omitted, the gateway uses the default (oldest) active connection.
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://gateway.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://gateway.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://gateway.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://ctrl.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://gateway.maton.ai/toggl-track/api/v9/me - Incorrect:
https://gateway.maton.ai/api/v9/me