Access the Clockify API with managed OAuth authentication. Track time, manage projects, clients, tasks, tags, and workspaces.
# Get current user
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/clockify/api/v1/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/clockify/{native-api-path}
Maton proxies requests to api.clockify.me and automatically injects your credentials.
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"
Manage your Clockify OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=clockify&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
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'clockify'}).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
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-13T09:18:02.529448Z",
"last_updated_time": "2026-02-13T09:18:09.334540Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "clockify",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
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
If you have multiple Clockify 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/clockify/api/v1/user')
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.
GET /clockify/api/v1/user
Response:
{
"id": "698eeb9f5cd3a921db12069f",
"email": "user@example.com",
"name": "John Doe",
"activeWorkspace": "698eeb9e5cd3a921db120693",
"defaultWorkspace": "698eeb9e5cd3a921db120693",
"status": "ACTIVE"
}
GET /clockify/api/v1/workspaces
GET /clockify/api/v1/workspaces/{workspaceId}
POST /clockify/api/v1/workspaces
Content-Type: application/json
{
"name": "My Workspace"
}
GET /clockify/api/v1/workspaces/{workspaceId}/users
GET /clockify/api/v1/workspaces/{workspaceId}/projects
GET /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}
POST /clockify/api/v1/workspaces/{workspaceId}/projects
Content-Type: application/json
{
"name": "My Project",
"isPublic": true,
"clientId": "optional-client-id"
}
Response:
{
"id": "698f7cba4f748f6209ea8995",
"name": "My Project",
"clientId": "",
"workspaceId": "698eeb9e5cd3a921db120693",
"billable": true,
"color": "#1976D2",
"archived": false,
"public": true
}
PUT /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}
Content-Type: application/json
{
"name": "Updated Project Name",
"archived": true
}
DELETE /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}
Note: You cannot delete active projects. Set archived: true first.
GET /clockify/api/v1/workspaces/{workspaceId}/clients
GET /clockify/api/v1/workspaces/{workspaceId}/clients/{clientId}
POST /clockify/api/v1/workspaces/{workspaceId}/clients
Content-Type: application/json
{
"name": "Acme Corp",
"address": "123 Main St",
"note": "Important client"
}
Response:
{
"id": "698f7cba0705b7d880830262",
"name": "Acme Corp",
"workspaceId": "698eeb9e5cd3a921db120693",
"archived": false,
"address": "123 Main St",
"note": "Important client"
}
PUT /clockify/api/v1/workspaces/{workspaceId}/clients/{clientId}
Content-Type: application/json
{
"name": "Acme Corporation"
}
DELETE /clockify/api/v1/workspaces/{workspaceId}/clients/{clientId}
GET /clockify/api/v1/workspaces/{workspaceId}/tags
GET /clockify/api/v1/workspaces/{workspaceId}/tags/{tagId}
POST /clockify/api/v1/workspaces/{workspaceId}/tags
Content-Type: application/json
{
"name": "urgent"
}
Response:
{
"id": "698f7cbbaa9e9f33e5fc0126",
"name": "urgent",
"workspaceId": "698eeb9e5cd3a921db120693",
"archived": false
}
PUT /clockify/api/v1/workspaces/{workspaceId}/tags/{tagId}
Content-Type: application/json
{
"name": "high-priority"
}
DELETE /clockify/api/v1/workspaces/{workspaceId}/tags/{tagId}
GET /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}/tasks
GET /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}/tasks/{taskId}
POST /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}/tasks
Content-Type: application/json
{
"name": "Implement feature",
"assigneeIds": ["user-id-1"],
"estimate": "PT2H",
"billable": true
}
Response:
{
"id": "698f7cc4aa9e9f33e5fc017b",
"name": "Implement feature",
"projectId": "698f7cba4f748f6209ea8995",
"assigneeIds": [],
"estimate": "PT0S",
"status": "ACTIVE",
"billable": true
}
PUT /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}/tasks/{taskId}
Content-Type: application/json
{
"name": "Updated task name",
"status": "DONE"
}
DELETE /clockify/api/v1/workspaces/{workspaceId}/projects/{projectId}/tasks/{taskId}
Note: You cannot delete active tasks. Set status: "DONE" first.
GET /clockify/api/v1/workspaces/{workspaceId}/user/{userId}/time-entries
Response:
[
{
"id": "698f7cc4aa9e9f33e5fc0180",
"description": "Working on project",
"userId": "698eeb9f5cd3a921db12069f",
"billable": true,
"projectId": "698f7cba4f748f6209ea8995",
"taskId": null,
"workspaceId": "698eeb9e5cd3a921db120693",
"timeInterval": {
"start": "2026-02-13T18:34:28Z",
"end": "2026-02-13T19:34:28Z",
"duration": "PT1H"
}
}
]
POST /clockify/api/v1/workspaces/{workspaceId}/time-entries
Content-Type: application/json
{
"start": "2026-02-13T09:00:00Z",
"end": "2026-02-13T10:00:00Z",
"description": "Team meeting",
"projectId": "project-id",
"taskId": "task-id",
"tagIds": ["tag-id-1", "tag-id-2"],
"billable": true
}
POST /clockify/api/v1/workspaces/{workspaceId}/user/{userId}/time-entries
Content-Type: application/json
{
"start": "2026-02-13T09:00:00Z",
"end": "2026-02-13T10:00:00Z",
"description": "Team meeting"
}
GET /clockify/api/v1/workspaces/{workspaceId}/time-entries/{timeEntryId}
PUT /clockify/api/v1/workspaces/{workspaceId}/time-entries/{timeEntryId}
Content-Type: application/json
{
"start": "2026-02-13T09:00:00Z",
"end": "2026-02-13T11:00:00Z",
"description": "Extended meeting"
}
DELETE /clockify/api/v1/workspaces/{workspaceId}/time-entries/{timeEntryId}
PATCH /clockify/api/v1/workspaces/{workspaceId}/user/{userId}/time-entries
Content-Type: application/json
{
"end": "2026-02-13T17:00:00Z"
}
GET /clockify/api/v1/workspaces/{workspaceId}/time-entries
Clockify uses page-based pagination:
GET /clockify/api/v1/workspaces/{workspaceId}/projects?page=1&page-size=50
Query Parameters:
page - Page number (1-indexed, default: 1)page-size - Items per page (default varies by endpoint)Response includes a Last-Page header indicating if there are more pages.
const response = await fetch(
'https://api.maton.ai/clockify/api/v1/workspaces',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const workspaces = await response.json();
import os
import requests
response = requests.get(
'https://api.maton.ai/clockify/api/v1/workspaces',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
workspaces = response.json()
import os
import requests
from datetime import datetime, timedelta, timezone
workspace_id = "your-workspace-id"
start_time = (datetime.now(timezone.utc) - timedelta(hours=1)).isoformat().replace('+00:00', 'Z')
end_time = datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
response = requests.post(
f'https://api.maton.ai/clockify/api/v1/workspaces/{workspace_id}/time-entries',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'start': start_time,
'end': end_time,
'description': 'Working on feature'
}
)
2026-02-13T09:00:00Z)PT1H for 1 hour, PT30M for 30 minutes)curl -g when URLs contain brackets to disable glob parsingjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Missing Clockify connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 429 | Rate limited (50 req/sec per workspace) |
| 4xx/5xx | Passthrough error from Clockify API |
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
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
clockify. For example:https://api.maton.ai/clockify/api/v1/userhttps://api.maton.ai/api/v1/user共 2 个版本