This API is currently under active development. Features and endpoints may change. We recommend testing thoroughly before production use.
This API endpoint is special: it does not need a session token. You only need your userId to authenticate. This makes it perfect for Siri Shortcuts, shell scripts, and background tasks where logging in is difficult.
⚠️ Note: Sessions shorter than 5 minutes are automatically discarded.
Use this endpoint to control the time tracker programmatically. It supports simple "start" and "stop" commands.
/api/automationuserId (required): Your unique User ID (found in profile)action (required): "start" or "stop"location (required for "start"): "home" or "office"curl -X POST https://timetracker.adatepe.dev/api/automation \
-H "Content-Type: application/json" \
-d '{
"userId": "YOUR_USER_ID_HERE",
"action": "start",
"location": "home"
}'curl -X POST https://timetracker.adatepe.dev/api/automation \
-H "Content-Type: application/json" \
-d '{
"userId": "YOUR_USER_ID_HERE",
"action": "stop"
}'You can trigger this API directly from your iPhone using the Shortcuts app. This is great for creating home screen icons or using with Siri.
Open Shortcuts app and create a new shortcut ("+")
Add action: Get Contents of URL
Set URL to:
https://timetracker.adatepe.dev/api/automationTap the arrow to expand options:
Content-Type, Value: application/jsonAdd new fields under Request Body:
userIdText (Your ID)actionText ("start" or "stop")locationText ("home" or "office")Pro Tip: Create two separate shortcuts: one for "Start Work" and one for "Stop Work". Add them to your Home Screen for one-tap time tracking!
The TimeTracker API allows you to programmatically track your work hours, retrieve statistics, and analyze your productivity patterns. Whether you're building a mobile app, setting up NFC tags, or integrating with other tools, this API makes it simple.
All API requests require authentication using Supabase Auth. Here's how to get your access token:
After logging into TimeTracker, you can retrieve your access token using the browser console. You can also find your User ID by clicking on your email in the top navigation bar.
// Open browser console (F12) while logged in to TimeTracker
const session = await supabase.auth.getSession();
console.log(session.data.session.access_token);
// Copy the token - you'll need it for API requestsImportant: Keep your access token secure! Don't share it publicly or commit it to version control.
Token Expiration: Access tokens expire after 1 hour. For automated scripts or NFC tags, you'll need to implement token refresh or use service role keys.
Add your access token to the Authorization header of every API request:
Authorization: Bearer YOUR_ACCESS_TOKEN_HEREAccess tokens expire after 1 hour. Here's how to refresh them:
// Check if token is expired and refresh
const { data: { session }, error } = await supabase.auth.getSession();
if (error || !session) {
// Session expired, refresh it
const { data: { session: newSession }, error: refreshError } =
await supabase.auth.refreshSession();
if (refreshError) {
console.error('Failed to refresh token:', refreshError);
// Redirect to login
} else {
// Use newSession.access_token for API calls
console.log('Token refreshed:', newSession.access_token);
}
} else {
// Use existing session.access_token
console.log('Token still valid:', session.access_token);
}Since NFC tags can't refresh tokens automatically, you have two options:
Instead of calling the API directly, your NFC tag calls a personal webhook/middleware service that handles authentication and token refresh for you.
Store your refresh token securely and use it to get a new access token before each API call. This adds complexity to your Shortcut/automation.
Use Supabase Service Role Key for server-side automations. Warning: This bypasses Row Level Security - only use in secure environments!
Authorization: Bearer YOUR_SUPABASE_SERVICE_ROLE_KEYLet's start by creating your first time entry. We'll log a work session from today.
This request creates a time entry with a start time. You can update it later with an end time.
curl -X POST https://timetracker.adatepe.dev/api/time-entries \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"date": "2025-01-15",
"start_time": "09:00",
"location": "office",
"user_id": "YOUR_USER_ID" // Optional: Validated against your token
}'const response = await fetch('https://timetracker.adatepe.dev/api/time-entries', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
date: '2025-01-15',
start_time: '09:00',
location: 'office'
})
});
const data = await response.json();
console.log('Entry created:', data);If successful, you'll receive a 201 status code with your time entry data:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "your-user-id",
"date": "2025-01-15",
"start_time": "09:00",
"end_time": null,
"location": "office",
"duration_minutes": null,
"created_at": "2025-01-15T09:00:00Z",
"updated_at": "2025-01-15T09:00:00Z"
}To add an end time, make another POST request with the same date:
const response = await fetch('https://timetracker.adatepe.dev/api/time-entries', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
date: '2025-01-15',
start_time: '09:00',
end_time: '17:30', // Added end time
location: 'office'
})
});/api/time-entriesCreate a new time entry or update an existing one for a specific date.
{
"date": "2025-01-15", // Required: YYYY-MM-DD
"start_time": "09:00", // Required: HH:mm
"end_time": "17:30", // Optional: HH:mm
"location": "office", // Required: "office" or "home"
"duration_minutes": 510, // Optional: auto-calculated
"user_id": "uuid" // Optional: Must match authenticated user
}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "your-user-id",
"date": "2025-01-15",
"start_time": "09:00",
"end_time": "17:30",
"location": "office",
"duration_minutes": 510,
"created_at": "2025-01-15T09:00:00Z",
"updated_at": "2025-01-15T17:30:00Z"
}/api/time-entriesRetrieve all your time entries, optionally filtered by date.
?date=2025-01-15&user_id=uuid(optional)[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"date": "2025-01-15",
"start_time": "09:00",
"end_time": "17:30",
"location": "office",
"duration_minutes": 510
}
]/api/time-entries/statsGet comprehensive statistics and analytics about your work patterns.
?days=30(optional, default: 30)?range=week(optional: "7d", "30d", "90d", "1y", "week", "month", "all"){
"stats": {
"totalHours": 168.5,
"totalDays": 21,
"homeOfficeDays": 8,
"officeDays": 13,
"averageHoursPerDay": 8.02,
"averageStartTime": "09:15",
"averageEndTime": "17:30",
"longestDay": 10.5,
"shortestDay": 6.25
},
"entries": [ /* all entries */ ]
}/api/time-entries/[id]Update a specific time entry by its ID. All fields are optional.
{
"end_time": "18:00", // Only update end time
"location": "home" // Or any other field
}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"date": "2025-01-15",
"start_time": "09:00",
"end_time": "18:00", // Updated
"location": "home", // Updated
"duration_minutes": 540
}These endpoints require a standard Bearer token authentication (as described in Section 2).
401 UnauthorizedMissing or invalid access token. Check your Authorization header.
404 Not FoundResource doesn't exist or you don't have access to it.
500 Internal Server ErrorServer error. Check your request format or contact support.