API Usage
Integrate any AI agent with TeeckIn using the REST API.
Overview
This page covers Client Credentials authentication for AI tools that don't support browser-based OAuth (like Cursor, Copilot, Windsurf, or custom integrations).
Using Claude Code?
Looking for the versioned API & Swagger docs?
/api/v1 surface and the interactive Swagger reference, see .When to Use Client Credentials
Use Client Credentials (API keys) when your AI tool:
- -Does not support OAuth 2.0 with PKCE (browser-based authentication)
- -Needs to authenticate non-interactively (CI/CD, scripts, hooks)
- -Is a custom integration you're building yourself
Authentication
Client Credentials authentication requires a Client ID and from your agent settings in TeeckIn. These are exchanged for a short-lived access token.
1. Get Access Token
curl -X POST https://teeckin.com/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=teeckin_agent_..." \
-d "client_secret=tcs_..."Returns an access token (valid for 1 hour):
{
"access_token": "tat_...",
"token_type": "Bearer",
"expires_in": 3600
}2. Use Access Token
curl https://teeckin.com/api/timer/active \
-H "Authorization: Bearer tat_..."Token Refresh
Simple Agent Endpoints
These simplified endpoints are designed for shell hooks and scripts. They accept topic names (fuzzy matched) in addition to IDs, making them ideal for Claude Code SessionEnd hooks.
GET /api/agent/topicsList available topics. Returns a flat list with category names.
Response:
{
"topics": [
{ "id": "top-456", "name": "Project Alpha", "category": "Client Work" },
{ "id": "top-789", "name": "Research", "category": "Internal" }
]
}GET /api/agent/timerCheck timer status.
Response:
{
"running": true,
"topic": { "id": "top-456", "name": "Project Alpha", "category": "Client Work" },
"elapsedMinutes": 45,
"startedAt": "2026-03-30T10:00:00Z"
}POST /api/agent/timer/startStart a timer. Accepts topic name (fuzzy matched) or ID.
Request Body:
{ "topic": "Project Alpha" }Response:
{
"started": true,
"topic": { "id": "top-456", "name": "Project Alpha", "category": "Client Work" }
}POST /api/agent/timer/stopStop the active timer. Perfect for SessionEnd hooks.
Response:
{
"stopped": true,
"duration": 45,
"clockedTimeId": "ct-789"
}POST /api/agent/timeLog a completed time entry without using the timer.
Request Body:
{
"topic": "Project Alpha",
"duration_minutes": 30,
"notes": "Completed code review"
}Response:
{
"logged": true,
"id": "ct-abc",
"topic": { "id": "top-456", "name": "Project Alpha", "category": "Client Work" },
"duration": 30
}GET /api/agent/tagsList available tags for categorizing time entries.
Response:
{
"tags": [
{ "id": "tag-123", "name": "bug-fix" },
{ "id": "tag-456", "name": "feature" },
{ "id": "tag-789", "name": "refactoring" }
]
}PATCH /api/agent/timerUpdate the active timer with notes describing the work.
Request Body:
{ "notes": "Implementing user authentication module" }Response:
{
"updated": true,
"clockedTimeId": "ct-789"
}POST /api/agent/timer/tagsAdd tags to the active timer. Tags are created if they don't exist.
Request Body:
{ "tags": ["refactoring", "performance"] }Response:
{
"added": true,
"clockedTimeId": "ct-789",
"tags": ["refactoring", "performance"]
}Full API Endpoints
These are the full API endpoints with more options and detailed responses. Use these when you need more control over the request.
GET /api/topics/for-agentList available topics with category groupings and hints for recent usage.
Response:
{
"categories": [
{
"id": "cat-123",
"name": "Client Work",
"topics": [
{ "id": "top-456", "name": "Project Alpha", "recentlyUsed": true },
{ "id": "top-789", "name": "Research", "recentlyUsed": false }
]
}
],
"recentTopicIds": ["top-456"],
"defaultTopicId": "top-456",
"organizationGuidance": "Use Project Alpha for client deliverables..."
}POST /api/timer/startStart a timer on a specific topic.
Request Body:
{ "topicId": "top-456" }Response:
{
"clockedTime": {
"id": "ct-789",
"topicId": "top-456",
"startTime": "2026-03-30T10:00:00Z"
}
}POST /api/timer/stopStop the active timer. Optionally add notes.
Request Body:
{ "notes": "Completed competitor analysis" }Response:
{
"clockedTime": {
"id": "ct-789",
"startTime": "2026-03-30T10:00:00Z",
"endTime": "2026-03-30T10:45:00Z"
}
}GET /api/timer/activeCheck if there's a running timer.
Response:
{
"active": true,
"clockedTime": {
"id": "ct-789",
"topicId": "top-456",
"startTime": "2026-03-30T10:00:00Z"
}
}POST /api/clocked-timesCreate a manual time entry (for retroactive logging).
Request Body:
{
"topicId": "top-456",
"startTime": "2026-03-30T09:00:00Z",
"endTime": "2026-03-30T10:30:00Z",
"type": "manual",
"notes": "Drafted quarterly report"
}Response:
{
"id": "ct-abc",
"topicId": "top-456",
"startTime": "2026-03-30T09:00:00Z",
"endTime": "2026-03-30T10:30:00Z"
}Rate Limits
Agent API calls have rate limits to prevent abuse:
| Operation | Limit |
|---|---|
| Read (GET) | 120 per minute |
| Write (POST/PATCH) | 30 per minute |
| Timer operations | 10 per minute |
Rate Limit Headers
X-RateLimit-Remaining header in responses to monitor your usage.Error Responses
Common error codes you may encounter:
401Request a new token using your client credentials
403Check agent status in Settings > Agents
404Use /api/topics/for-agent to get valid IDs
429Wait and retry after the limit resets
Best Practices
- 1.Cache the topic list and refresh only when needed
- 2.Always stop timers when work completes
- 3.Include meaningful notes describing what was done
- 4.Handle rate limits gracefully with exponential backoff
- 5.Store client secrets securely and keep config files out of git
- 6.Rotate secrets periodically via Settings > Agents > Secrets tab