# TimeFly API - **OpenAPI Version:** `3.1.1` - **API Version:** `1.0.0` TimeFly is a platform for developers to automatically and accurately track and analyze programming time. This API serves as the backend for our VS Code extension integration, allowing users to sign in with Google, manage sessions, and query productivity statistics. **Authentication:** - Web users authenticate via secure cookie (token) after Google login. - IDE extensions and integrations authenticate using an API key via the X-API-Key header. **Rate-Limiting:** - Global quota: **100 requests per minute** per user/IP. - Sensitive endpoints (e.g., `/api/auth/refresh`) have stricter limits (5 req/min). - On exceeding the limit the API returns **HTTP 429** and sets `X-RateLimit-*` headers. - Check your current quota with **GET /api/rate-limit**. **Key Features:** - Direct integration with VS Code via extension - Real-time activity tracking and synchronization - High-performance time-series analytics with ClickHouse - Secure authentication with Google OAuth2 - User and session management - Well-documented and easy-to-consume API - Designed for teams and individual developers **Who is it for?** - Developers who want to understand and optimize their programming time - Teams seeking objective productivity metrics - Anyone interested in quantifying their workflow in the editor. Visit [timefly.dev](https://timefly.dev) for more information. ## Servers - **URL:** `https://api.timefly.dev:3001` - **Description:** Server URL ## Operations ### Initiate Google OAuth2 Login - **Method:** `GET` - **Path:** `/api/auth/google` - **Tags:** Auth Redirects the user to the Google OAuth2 consent screen to begin the authentication process. #### Responses ##### Status: 302 Redirect to Google OAuth2 consent screen. ### Handle Google OAuth2 Callback - **Method:** `GET` - **Path:** `/api/auth/google/callback` - **Tags:** Auth Handles the callback from Google after user authentication. Exchanges the authorization code for tokens, creates a user session by setting a secure `httpOnly` cookie, and redirects to the frontend application. On error, redirects to a frontend error page with details in the query parameters. #### Responses ##### Status: 302 Redirects to the frontend application (on success) or an error page (on failure). Sets the \`token\` cookie on success. ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### User Logout (Current Session) - **Method:** `GET` - **Path:** `/api/auth/logout` - **Tags:** Auth Logs the user out by revoking the current session and clearing authentication cookies. For multi-session management (close specific sessions or all sessions), use the dedicated session endpoints under /api/users/{uuid}/sessions. #### Responses ##### Status: 200 Logout successful - current session revoked and cookies cleared ###### Content-Type: application/json - **`message`** `string` - **`ok`** `boolean` **Example:** ``` { "ok": true, "message": "Logged out successfully. Cookies cleared and session revoked." } ``` ### Refresh access token using a valid refresh token cookie - **Method:** `POST` - **Path:** `/api/auth/refresh` - **Tags:** Auth Issues a new access token and refresh token if the provided refresh token is valid. Returns both as httpOnly cookies. #### Responses ##### Status: 200 Tokens refreshed successfully ###### Content-Type: application/json - **`ok`** `boolean` **Example:** ``` { "ok": true } ``` ##### Status: 401 Invalid or expired refresh token ###### Content-Type: application/json - **`message`** `string` - **`ok`** `boolean` **Example:** ``` { "ok": false, "message": "" } ``` ##### Status: 429 Too many refresh attempts (rate limited) ###### Content-Type: application/json - **`message`** `string` **Example:** ``` { "message": "Too many requests – retry after 57 seconds" } ``` ### Get user's total coding time - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/total-time` - **Tags:** Analytics #### Responses ##### Status: 200 Total time in milliseconds ###### Content-Type: application/json - **`totalMs` (required)** `number` **Example:** ``` { "totalMs": 1 } ``` ### Get activity heatmap with daily/weekly/monthly averages - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/activity-heatmap` - **Tags:** Analytics #### Responses ##### Status: 200 Activity heatmap response ###### Content-Type: application/json - **`dailyAverageMs` (required)** `number` - **`maxDailyMs` (required)** `number` - **`monthlyAverageMs` (required)** `number` - **`weeklyAverageMs` (required)** `number` - **`weeks` (required)** `array` **Items:** - **`days` (required)** `array` **Items:** - **`day` (required)** `string` - **`topLanguage` (required)** `string | null` - **`topProject` (required)** `string | null` - **`totalMs` (required)** `number` - **`weekIndex` (required)** `number` **Example:** ``` { "dailyAverageMs": 1, "weeklyAverageMs": 1, "monthlyAverageMs": 1, "maxDailyMs": 1, "weeks": [ { "weekIndex": 1, "days": [ { "day": "", "totalMs": 1, "topProject": null, "topLanguage": null } ] } ] } ``` ### Weekly coding sessions with aggregate stats - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/coding-sessions` - **Tags:** Analytics #### Responses ##### Status: 200 Coding sessions summary ###### Content-Type: application/json - **`days` (required)** `array` **Items:** - **`date` (required)** `string` - **`sessions` (required)** `array` **Items:** - **`end` (required)** `string` - **`interruptions` (required)** `number` - **`languages` (required)** `array` **Items:** `array` - **`projects` (required)** `array` **Items:** `array` - **`start` (required)** `string` - **`totalMs` (required)** `number` - **`stats` (required)** `object` - **`avgInterruptionsPerSession` (required)** `number` - **`avgLongestSessionStart` (required)** `string` - **`avgSessionLengthMsPerDay` (required)** `number` - **`avgSessionsPerDay` (required)** `number` **Example:** ``` { "days": [ { "date": "", "sessions": [ { "start": "", "end": "", "totalMs": 1, "projects": [ [] ], "languages": [ [] ], "interruptions": 1 } ] } ], "stats": { "avgSessionLengthMsPerDay": 1, "avgSessionsPerDay": 1, "avgInterruptionsPerSession": 1, "avgLongestSessionStart": "" } } ``` ### Get coding timeline for a given day (merged blocks) - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/activity-timeline` - **Tags:** Analytics #### Responses ##### Status: 200 Timeline blocks ###### Content-Type: application/json **Array of:** - **`end` (required)** `string` - **`languages` (required)** `array` **Items:** `array` - **`projects` (required)** `array` **Items:** `array` - **`start` (required)** `string` - **`totalMs` (required)** `number` **Example:** ``` [ { "start": "", "end": "", "totalMs": 1, "projects": [ [] ], "languages": [ [] ] } ] ``` ### Get most active day/week/month summary breakdown - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/activity-summary` - **Tags:** Analytics #### Responses ##### Status: 200 Activity summary response ###### Content-Type: application/json - **`mostActiveDay` (required)** `object | null` - **`devices` (required)** `object` - **`ides` (required)** `object` - **`languages` (required)** `object` - **`osPlatforms` (required)** `object` - **`period` (required)** `string` - **`projects` (required)** `object` - **`totalMs` (required)** `number` - **`mostActiveMonth` (required)** `object | null` - **`devices` (required)** `object` - **`ides` (required)** `object` - **`languages` (required)** `object` - **`osPlatforms` (required)** `object` - **`period` (required)** `string` - **`projects` (required)** `object` - **`totalMs` (required)** `number` - **`mostActiveWeek` (required)** `object | null` - **`devices` (required)** `object` - **`ides` (required)** `object` - **`languages` (required)** `object` - **`osPlatforms` (required)** `object` - **`period` (required)** `string` - **`projects` (required)** `object` - **`totalMs` (required)** `number` **Example:** ``` { "mostActiveDay": { "period": "", "totalMs": 1, "projects": { "propertyName*": 1 }, "languages": { "propertyName*": 1 }, "ides": { "propertyName*": 1 }, "osPlatforms": { "propertyName*": 1 }, "devices": { "propertyName*": 1 } }, "mostActiveWeek": { "period": "", "totalMs": 1, "projects": { "propertyName*": 1 }, "languages": { "propertyName*": 1 }, "ides": { "propertyName*": 1 }, "osPlatforms": { "propertyName*": 1 }, "devices": { "propertyName*": 1 } }, "mostActiveMonth": { "period": "", "totalMs": 1, "projects": { "propertyName*": 1 }, "languages": { "propertyName*": 1 }, "ides": { "propertyName*": 1 }, "osPlatforms": { "propertyName*": 1 }, "devices": { "propertyName*": 1 } } } ``` ### Get projects with time spent in specified range - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/projects` - **Tags:** Analytics #### Responses ##### Status: 200 Projects with time spent and metadata ###### Content-Type: application/json - **`periodEnd` (required)** `string | null` - **`periodStart` (required)** `string | null` - **`projects` (required)** `array` **Items:** - **`lastActivity` (required)** `string` - **`percentage` (required)** `number` - **`projectId` (required)** `string` - **`totalMs` (required)** `number` - **`totalMs` (required)** `number` **Example:** ``` { "projects": [ { "projectId": "", "totalMs": 1, "percentage": 1, "lastActivity": "" } ], "totalMs": 1, "periodStart": null, "periodEnd": null } ``` ### Get daily recap for yesterday with timeline and project breakdown - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/daily-recap` - **Tags:** Analytics #### Responses ##### Status: 200 Daily recap with timeline and project breakdown ###### Content-Type: application/json - **`date` (required)** `string` - **`projects` (required)** `array` **Items:** - **`files` (required)** `array` **Items:** - **`events` (required)** `array` **Items:** - **`timestamp` (required)** `string` - **`type` (required)** `string` - **`details`** `object` - **`fileName` (required)** `string` - **`filePath` (required)** `string` - **`timeSpent` (required)** `number` - **`language`** `string` - **`projectName` (required)** `string` - **`totalTime` (required)** `number` - **`summary` (required)** `object` - **`productiveTime` (required)** `number` - **`totalFiles` (required)** `number` - **`totalProjects` (required)** `number` - **`unproductiveTime` (required)** `number` - **`timeline` (required)** `array` **Items:** - **`activityType` (required)** `string` - **`duration` (required)** `number` - **`endTime` (required)** `string` - **`file` (required)** `string` - **`id` (required)** `string` - **`productive` (required)** `boolean` - **`project` (required)** `string` - **`startTime` (required)** `string` - **`totalTime` (required)** `number` **Example:** ``` { "date": "", "totalTime": 1, "projects": [ { "projectName": "", "totalTime": 1, "files": [ { "fileName": "", "filePath": "", "language": "", "timeSpent": 1, "events": [ { "type": "", "timestamp": "", "details": { "propertyName*": "anything" } } ] } ] } ], "timeline": [ { "id": "", "startTime": "", "endTime": "", "duration": 1, "project": "", "file": "", "activityType": "", "productive": true } ], "summary": { "totalProjects": 1, "totalFiles": 1, "productiveTime": 1, "unproductiveTime": 1 } } ``` ### Get per-day project stacked summary for a period - **Method:** `GET` - **Path:** `/api/users/{uuid}/analytics/project-summary` - **Tags:** Analytics #### Responses ##### Status: 200 Project summary stacked by day ###### Content-Type: application/json - **`buckets` (required)** `array` **Items:** - **`date` (required)** `string` - **`items` (required)** `array` **Items:** - **`projectId` (required)** `string` - **`projectName` (required)** `string` - **`totalMs` (required)** `number` - **`displayLabel`** `string` - **`end`** `string` - **`start`** `string` - **`granularity` (required)** `string`, possible values: `"day", "week", "month", "weekday", "hour"` - **`periodEnd` (required)** `string | null` - **`periodStart` (required)** `string | null` - **`totals` (required)** `object` - **`projects` (required)** `array` **Items:** - **`percentage` (required)** `number` - **`projectId` (required)** `string` - **`projectName` (required)** `string` - **`totalMs` (required)** `number` - **`totalMs` (required)** `number` - **`unit` (required)** `string` - **`timezone`** `string` **Example:** ``` { "periodStart": null, "periodEnd": null, "timezone": "", "granularity": "day", "unit": "", "buckets": [ { "date": "", "displayLabel": "", "start": "", "end": "", "items": [ { "projectId": "", "projectName": "", "totalMs": 1 } ] } ], "totals": { "totalMs": 1, "projects": [ { "projectId": "", "projectName": "", "totalMs": 1, "percentage": 1 } ] } } ``` ### Get current authenticated user - **Method:** `GET` - **Path:** `/api/users/me` - **Tags:** User Returns the currently authenticated user based on the JWT session. Requires authentication. Useful for profile pages or session checks. #### Responses ##### Status: 200 Authenticated user ###### Content-Type: application/json - **`createdAt` (required)** `string` — User creation date - **`email` (required)** `string`, format: `email` — User email address - **`name` (required)** `string` — Full name of the user - **`updatedAt` (required)** `string` — User last update date - **`uuid` (required)** `string`, format: `uuid` — Public UUID for the user - **`avatarUrl`** `string`, format: `uri` — URL to the user avatar image - **`deletedAt`** `string` — Soft delete timestamp - **`providerIdentities`** `array` — List of linked provider identities for this user **Items:** - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.969Z", "updatedAt": "2025-08-24T16:23:49.969Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] } ``` ##### Status: 401 Unauthorized. No valid session or token. ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### List all users - **Method:** `GET` - **Path:** `/api/users` - **Tags:** User Returns a list of all users in the system. Only accessible to admins or for debugging purposes. #### Responses ##### Status: 200 List of users ###### Content-Type: application/json **Array of:** - **`createdAt` (required)** `string` — User creation date - **`email` (required)** `string`, format: `email` — User email address - **`name` (required)** `string` — Full name of the user - **`updatedAt` (required)** `string` — User last update date - **`uuid` (required)** `string`, format: `uuid` — Public UUID for the user - **`avatarUrl`** `string`, format: `uri` — URL to the user avatar image - **`deletedAt`** `string` — Soft delete timestamp - **`providerIdentities`** `array` — List of linked provider identities for this user **Items:** - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` [ { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.969Z", "updatedAt": "2025-08-24T16:23:49.969Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] } ] ``` ##### Status: 500 Server error ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Create a new user - **Method:** `POST` - **Path:** `/api/users` - **Tags:** User Creates a new user in the system. Used for registration or admin user creation. #### Request Body ##### Content-Type: application/json **Example:** ``` null ``` #### Responses ##### Status: 201 User created ###### Content-Type: application/json - **`createdAt` (required)** `string` — User creation date - **`email` (required)** `string`, format: `email` — User email address - **`name` (required)** `string` — Full name of the user - **`updatedAt` (required)** `string` — User last update date - **`uuid` (required)** `string`, format: `uuid` — Public UUID for the user - **`avatarUrl`** `string`, format: `uri` — URL to the user avatar image - **`deletedAt`** `string` — Soft delete timestamp - **`providerIdentities`** `array` — List of linked provider identities for this user **Items:** - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.969Z", "updatedAt": "2025-08-24T16:23:49.969Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] } ``` ##### Status: 400 Invalid input ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Get user by UUID - **Method:** `GET` - **Path:** `/api/users/{uuid}` - **Tags:** User Returns a user by their public UUID. Does not expose internal IDs. Useful for profile pages or admin panels. #### Responses ##### Status: 200 User found ###### Content-Type: application/json - **`createdAt` (required)** `string` — User creation date - **`email` (required)** `string`, format: `email` — User email address - **`name` (required)** `string` — Full name of the user - **`updatedAt` (required)** `string` — User last update date - **`uuid` (required)** `string`, format: `uuid` — Public UUID for the user - **`avatarUrl`** `string`, format: `uri` — URL to the user avatar image - **`deletedAt`** `string` — Soft delete timestamp - **`providerIdentities`** `array` — List of linked provider identities for this user **Items:** - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.969Z", "updatedAt": "2025-08-24T16:23:49.969Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] } ``` ##### Status: 404 User not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Update user by UUID - **Method:** `PUT` - **Path:** `/api/users/{uuid}` - **Tags:** User Updates user information by their UUID. Only allowed for the user themselves or admins. #### Request Body ##### Content-Type: application/json **Example:** ``` null ``` #### Responses ##### Status: 200 User updated ###### Content-Type: application/json - **`createdAt` (required)** `string` — User creation date - **`email` (required)** `string`, format: `email` — User email address - **`name` (required)** `string` — Full name of the user - **`updatedAt` (required)** `string` — User last update date - **`uuid` (required)** `string`, format: `uuid` — Public UUID for the user - **`avatarUrl`** `string`, format: `uri` — URL to the user avatar image - **`deletedAt`** `string` — Soft delete timestamp - **`providerIdentities`** `array` — List of linked provider identities for this user **Items:** - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.969Z", "updatedAt": "2025-08-24T16:23:49.969Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] } ``` ##### Status: 400 Invalid input ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 User not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Soft delete user by UUID - **Method:** `DELETE` - **Path:** `/api/users/{uuid}` - **Tags:** User Soft deletes a user by their UUID. The user is not removed from the database but marked as deleted. #### Responses ##### Status: 200 User soft deleted ###### Content-Type: application/json - **`ok`** `boolean` **Example:** ``` { "ok": true } ``` ##### Status: 404 User not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### List all sessions for a user - **Method:** `GET` - **Path:** `/api/users/{uuid}/sessions` - **Tags:** User Sessions #### Responses ##### Status: 200 List of sessions ###### Content-Type: application/json **Array of:** - **`createdAt` (required)** `string` — Session creation timestamp - **`expiresAt` (required)** `string` — Session expiration timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — Session UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`ipAddress`** `string | null` — IP address - **`revokedAt`** `string | null` — Revocation timestamp - **`userAgent`** `string | null` — User agent string **Example:** ``` [ { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "userAgent": "Mozilla/5.0", "ipAddress": "192.168.1.1", "createdAt": "2025-08-24T16:23:49.970Z", "expiresAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ] ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Revoke all sessions for a user - **Method:** `DELETE` - **Path:** `/api/users/{uuid}/sessions` - **Tags:** User Sessions #### Responses ##### Status: 200 All sessions revoked ###### Content-Type: application/json - **`ok`** `boolean` - **`revoked`** `number` **Example:** ``` { "ok": true, "revoked": 3 } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### List active sessions for a user - **Method:** `GET` - **Path:** `/api/users/{uuid}/sessions/active` - **Tags:** User Sessions #### Responses ##### Status: 200 List of active sessions ###### Content-Type: application/json **Array of:** - **`createdAt` (required)** `string` — Session creation timestamp - **`expiresAt` (required)** `string` — Session expiration timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — Session UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`ipAddress`** `string | null` — IP address - **`revokedAt`** `string | null` — Revocation timestamp - **`userAgent`** `string | null` — User agent string **Example:** ``` [ { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "userAgent": "Mozilla/5.0", "ipAddress": "192.168.1.1", "createdAt": "2025-08-24T16:23:49.970Z", "expiresAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ] ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Get details of a session - **Method:** `GET` - **Path:** `/api/users/{uuid}/sessions/{sessionId}` - **Tags:** User Sessions #### Responses ##### Status: 200 Session details ###### Content-Type: application/json - **`createdAt` (required)** `string` — Session creation timestamp - **`expiresAt` (required)** `string` — Session expiration timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — Session UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`ipAddress`** `string | null` — IP address - **`revokedAt`** `string | null` — Revocation timestamp - **`userAgent`** `string | null` — User agent string **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "userAgent": "Mozilla/5.0", "ipAddress": "192.168.1.1", "createdAt": "2025-08-24T16:23:49.970Z", "expiresAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 Session not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Revoke a specific session - **Method:** `DELETE` - **Path:** `/api/users/{uuid}/sessions/{sessionId}` - **Tags:** User Sessions #### Responses ##### Status: 200 Session revoked ###### Content-Type: application/json - **`ok`** `boolean` **Example:** ``` { "ok": true } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 Session not found or already revoked ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### List all API keys for a user - **Method:** `GET` - **Path:** `/api/users/{uuid}/api-keys` - **Tags:** User API Keys Returns all API keys (metadata only, never the secret value) for the user. The real API key value is only shown once, at creation or regeneration. If you lose it, you must regenerate a new one. #### Responses ##### Status: 200 List of API keys ###### Content-Type: application/json **Array of:** - **`createdAt` (required)** `string` — API key creation timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — API Key UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`description`** `string` — Description of the API key usage - **`label`** `string` — Friendly label for the API key - **`revokedAt`** `string | null` — Revocation timestamp **Example:** ``` [ { "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "My App Key", "description": "Key for syncing with my app", "createdAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ] ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Create a new API key for a user - **Method:** `POST` - **Path:** `/api/users/{uuid}/api-keys` - **Tags:** User API Keys Creates a new API key for the user. Use this key with the X-API-Key header for IDE extensions and integrations. The real API key value is only shown once in the response. If you lose it, you must regenerate a new one. #### Request Body ##### Content-Type: application/json - **`description`** `string` - **`label`** `string` **Example:** ``` { "label": "My App Key", "description": "Key for syncing with my app" } ``` #### Responses ##### Status: 201 API key created. The real API key value is only shown once in this response. ###### Content-Type: application/json - **`apiKey`** `string` — The newly generated API key. It starts with the prefix \`tfk\_\`. This is the only time the key is shown in plaintext. - **`apiKeyPublic`** `object` — User API key object (public) - **`createdAt` (required)** `string` — API key creation timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — API Key UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`description`** `string` — Description of the API key usage - **`label`** `string` — Friendly label for the API key - **`revokedAt`** `string | null` — Revocation timestamp **Example:** ``` { "apiKey": "tfk_S25nIOfC_Tle6S3eE-23y5sftwzPj4aF", "apiKeyPublic": { "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "My App Key", "description": "Key for syncing with my app", "createdAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } } ``` ##### Status: 400 Invalid input ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Revoke all API keys for a user - **Method:** `DELETE` - **Path:** `/api/users/{uuid}/api-keys` - **Tags:** User API Keys Revokes (deletes) all API keys for the user. #### Responses ##### Status: 200 All API keys revoked ###### Content-Type: application/json - **`ok`** `boolean` - **`revoked`** `number` **Example:** ``` { "ok": true, "revoked": 2 } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### List active API keys for a user - **Method:** `GET` - **Path:** `/api/users/{uuid}/api-keys/active` - **Tags:** User API Keys Returns only active (not revoked) API keys for the user. #### Responses ##### Status: 200 List of active API keys ###### Content-Type: application/json **Array of:** - **`createdAt` (required)** `string` — API key creation timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — API Key UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`description`** `string` — Description of the API key usage - **`label`** `string` — Friendly label for the API key - **`revokedAt`** `string | null` — Revocation timestamp **Example:** ``` [ { "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "My App Key", "description": "Key for syncing with my app", "createdAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ] ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Get details of an API key - **Method:** `GET` - **Path:** `/api/users/{uuid}/api-keys/{keyUuid}` - **Tags:** User API Keys Returns metadata for a specific API key (never the secret value). The real API key value is only shown once, at creation or regeneration. #### Responses ##### Status: 200 API key details ###### Content-Type: application/json - **`createdAt` (required)** `string` — API key creation timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — API Key UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`description`** `string` — Description of the API key usage - **`label`** `string` — Friendly label for the API key - **`revokedAt`** `string | null` — Revocation timestamp **Example:** ``` { "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "My App Key", "description": "Key for syncing with my app", "createdAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 API key not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Revoke a specific API key - **Method:** `DELETE` - **Path:** `/api/users/{uuid}/api-keys/{keyUuid}` - **Tags:** User API Keys Revokes (deletes) a specific API key for the user. #### Responses ##### Status: 200 API key revoked ###### Content-Type: application/json - **`ok`** `boolean` **Example:** ``` { "ok": true } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 API key not found or already revoked ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Regenerate an API key - **Method:** `POST` - **Path:** `/api/users/{uuid}/api-keys/{keyUuid}/regenerate` - **Tags:** User API Keys Revokes the old API key and creates a new one with the same label and description. Use this key with the X-API-Key header for IDE extensions and integrations. The real API key value is only shown once in the response. If you lose it, you must regenerate a new one. #### Responses ##### Status: 200 API key regenerated. The real API key value is only shown once in this response. ###### Content-Type: application/json - **`apiKey`** `string` — The newly generated API key. It starts with the prefix \`tfk\_\`. This is the only time the key is shown in plaintext. - **`apiKeyPublic`** `object` — User API key object (public) - **`createdAt` (required)** `string` — API key creation timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — API Key UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`description`** `string` — Description of the API key usage - **`label`** `string` — Friendly label for the API key - **`revokedAt`** `string | null` — Revocation timestamp **Example:** ``` { "apiKey": "tfk_S25nIOfC_Tle6S3eE-23y5sftwzPj4aF", "apiKeyPublic": { "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "My App Key", "description": "Key for syncing with my app", "createdAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } } ``` ##### Status: 401 Unauthorized ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 API key not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Verify API key validity - **Method:** `POST` - **Path:** `/api/users/{uuid}/api-keys/verify` - **Tags:** User API Keys Verifies if the provided API key (via X-API-Key header) is valid and returns the associated user information. This endpoint validates that the API key exists, is not revoked, is not deleted, and belongs to an active user. The last\_used\_at timestamp is updated upon successful verification. #### Request Body ##### Content-Type: application/json **Example:** ``` {} ``` #### Responses ##### Status: 200 API key verification result. Returns validity status and user information if valid. ###### Content-Type: application/json - **`apiKeyUuid` (required)** `string`, format: `uuid` — UUID of the verified API key - **`user` (required)** `object` — User information associated with the API key - **`valid` (required)** `boolean` — Whether the API key is valid and active **Example:** ``` { "valid": true, "user": { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.971Z", "updatedAt": "2025-08-24T16:23:49.971Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] }, "apiKeyUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" } ``` ##### Status: 401 Invalid, revoked, or missing API key ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 Associated user not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 500 Internal server error ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### List data transfer events for user - **Method:** `GET` - **Path:** `/api/users/{uuid}/data-events` - **Tags:** Data Events #### Responses ##### Status: 200 List of events ###### Content-Type: application/json **Array of:** - **`created_at` (required)** `string` - **`event_type` (required)** `string`, possible values: `"import", "export"` - **`file_key` (required)** `string` - **`id` (required)** `string`, format: `uuid` - **`status` (required)** `string`, possible values: `"queued", "running", "done", "error"` - **`user_id` (required)** `string`, format: `uuid` - **`completed_at`** `string | null` - **`duration_seconds`** `number | null` - **`error_msg`** `string | null` - **`expires_at`** `string | null` - **`file_size_bytes`** `integer` - **`provider`** `string` - **`rows_count`** `integer` - **`sha1`** `string` - **`started_at`** `string | null` **Example:** ``` [ { "id": "", "user_id": "", "event_type": "import", "status": "queued", "file_key": "", "sha1": "", "file_size_bytes": 1, "rows_count": 1, "provider": "", "created_at": "", "started_at": null, "completed_at": null, "duration_seconds": null, "error_msg": null, "expires_at": null } ] ``` ### Get single data-event job by ID - **Method:** `GET` - **Path:** `/api/users/{uuid}/data-events/{eventId}` - **Tags:** Data Events #### Responses ##### Status: 200 DataEvent object ###### Content-Type: application/json **Example:** ``` {} ``` ##### Status: 404 Not found ### Export user data (queued job) - **Method:** `POST` - **Path:** `/api/users/{uuid}/data-events/export` - **Tags:** Data Events #### Responses ##### Status: 202 Export job queued ###### Content-Type: application/json - **`eventId`** `string` **Example:** ``` { "eventId": "" } ``` ### Import user data (queued job) - **Method:** `POST` - **Path:** `/api/users/{uuid}/data-events/import` - **Tags:** Data Events #### Request Body ##### Content-Type: application/json - **`fileKey` (required)** `string` — Key of the archive previously uploaded to S3 - **`provider` (required)** `string` — Data source identifier (e.g. wakatime) **Example:** ``` { "fileKey": "", "provider": "" } ``` #### Responses ##### Status: 202 Import job queued ###### Content-Type: application/json - **`eventId`** `string` **Example:** ``` { "eventId": "" } ``` ##### Status: 400 Missing fileKey ###### Content-Type: application/json **Example:** ``` {} ``` ##### Status: 409 Duplicate import (same SHA-1 previously processed) ###### Content-Type: application/json - **`message`** `string` **Example:** ``` { "message": "Duplicate import detected" } ``` ##### Status: 429 Rate limit exceeded – only one import job allowed per 30 days ###### Content-Type: application/json - **`message`** `string` **Example:** ``` { "message": "Too many requests" } ``` ### Generate presigned S3 URL for data dump upload (provider-agnostic) - **Method:** `POST` - **Path:** `/api/users/{uuid}/data-events/presign` - **Tags:** Data Events #### Request Body ##### Content-Type: application/json - **`ext`** `string` — Optional file extension, default json.gz - **`provider`** `string`, default: `"wakatime"` — Data source identifier (e.g. wakatime) **Example:** ``` { "provider": "wakatime", "ext": "" } ``` #### Responses ##### Status: 200 Presigned URL generated ###### Content-Type: application/json - **`fileKey`** `string` - **`uploadUrl`** `string`, format: `uri` **Example:** ``` { "uploadUrl": "", "fileKey": "" } ``` ##### Status: 429 Too many presign requests ###### Content-Type: application/json **Example:** ``` {} ``` ### Synchronise IDE events - **Method:** `POST` - **Path:** `/api/sync` - **Tags:** Events Sync #### Request Body ##### Content-Type: application/json - **`events` (required)** `array` **Items:** - **`activities` (required)** `array` **Items:** - **`name` (required)** `string` - **`properties`** `object` - **`event_duration_ms` (required)** `integer` - **`event_id` (required)** `string`, format: `uuid` - **`event_time` (required)** `string`, format: `date-time` - **`metadata` (required)** `object` - **`project_id` (required)** `string` - **`user_id`** `string`, format: `uuid` **Example:** ``` { "events": [ { "event_id": "", "user_id": "", "project_id": "", "event_time": "", "event_duration_ms": 1, "metadata": { "propertyName*": "anything" }, "activities": [ { "name": "", "properties": { "propertyName*": "anything" } } ] } ] } ``` #### Responses ##### Status: 200 Events synced ### Verify API key validity (standalone) - **Method:** `POST` - **Path:** `/api/api-keys/verify` - **Tags:** API Keys Verifies if the provided API key (via X-API-Key header) is valid and returns the associated user information. This endpoint does not require knowing the user UUID beforehand - perfect for IDE extensions and integrations. The endpoint validates that the API key exists, is not revoked, is not deleted, and belongs to an active user. The last\_used\_at timestamp is updated upon successful verification. #### Request Body ##### Content-Type: application/json **Example:** ``` {} ``` #### Responses ##### Status: 200 API key verification result. Returns validity status and user information if valid. ###### Content-Type: application/json - **`apiKeyUuid` (required)** `string`, format: `uuid` — UUID of the verified API key - **`user` (required)** `object` — User information associated with the API key - **`valid` (required)** `boolean` — Whether the API key is valid and active **Example:** ``` { "valid": true, "user": { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.971Z", "updatedAt": "2025-08-24T16:23:49.971Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] }, "apiKeyUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" } ``` ##### Status: 401 Invalid, revoked, or missing API key ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 404 Associated user not found ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ##### Status: 500 Internal server error ###### Content-Type: application/json - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### Get current rate-limit status - **Method:** `GET` - **Path:** `/api/rate-limit` - **Tags:** Rate Limit Returns the number of remaining requests and the timestamp when the quota resets for the authenticated user (or IP if not authenticated). #### Responses ##### Status: 200 Current rate-limit info ###### Content-Type: application/json - **`limit`** `number` - **`remaining`** `number` - **`reset`** `number` **Example:** ``` { "limit": 100, "remaining": 42, "reset": 1714765812 } ``` ### List pricing tiers - **Method:** `GET` - **Path:** `/api/pricing` - **Tags:** Pricing #### Responses ##### Status: 200 List of tiers ###### Content-Type: application/json **Array of:** - **`apiKeyLimit` (required)** `number` - **`name` (required)** `string` - **`rateLimit` (required)** `number` - **`description`** `string | null` — Tier description - **`stripeProductId`** `string | null` **Example:** ``` [ { "name": "Pro", "description": "Professional tier with all features", "rateLimit": 1000, "apiKeyLimit": 20, "stripeProductId": "prod_Siqa3ELSbzL8yl" } ] ``` ## Schemas ### ErrorResponse - **Type:**`object` Standard error response. - **`error` (required)** `object` - **`message` (required)** `string` — Human-readable error message. - **`status` (required)** `number` - **`ok` (required)** `boolean` **Example:** ``` { "ok": false, "error": { "message": "Invalid authorization code.", "status": 401 } } ``` ### User - **Type:**`object` User object returned by the API. Contains all public user information and linked provider identities. - **`createdAt` (required)** `string` — User creation date - **`email` (required)** `string`, format: `email` — User email address - **`name` (required)** `string` — Full name of the user - **`updatedAt` (required)** `string` — User last update date - **`uuid` (required)** `string`, format: `uuid` — Public UUID for the user - **`avatarUrl`** `string`, format: `uri` — URL to the user avatar image - **`deletedAt`** `string` — Soft delete timestamp - **`providerIdentities`** `array` — List of linked provider identities for this user **Items:** - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.969Z", "updatedAt": "2025-08-24T16:23:49.969Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] } ``` ### ProviderIdentity - **Type:**`object` Represents a user identity from an external authentication provider. - **`provider` (required)** `string` — The name of the authentication provider (e.g., google, github, email). - **`providerUserId` (required)** `string` — The unique user ID assigned by the provider. **Example:** ``` { "provider": "google", "providerUserId": "1234567890" } ``` ### Session - **Type:**`object` User session object - **`createdAt` (required)** `string` — Session creation timestamp - **`expiresAt` (required)** `string` — Session expiration timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — Session UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`ipAddress`** `string | null` — IP address - **`revokedAt`** `string | null` — Revocation timestamp - **`userAgent`** `string | null` — User agent string **Example:** ``` { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "userAgent": "Mozilla/5.0", "ipAddress": "192.168.1.1", "createdAt": "2025-08-24T16:23:49.970Z", "expiresAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ``` ### ApiKey - **Type:**`object` User API key object (public) - **`createdAt` (required)** `string` — API key creation timestamp - **`lastUsedAt` (required)** `string` — Last used timestamp - **`uuid` (required)** `string`, format: `uuid` — API Key UUID - **`deletedAt`** `string | null` — Soft delete timestamp - **`description`** `string` — Description of the API key usage - **`label`** `string` — Friendly label for the API key - **`revokedAt`** `string | null` — Revocation timestamp **Example:** ``` { "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "My App Key", "description": "Key for syncing with my app", "createdAt": "2025-08-24T16:23:49.970Z", "lastUsedAt": "2025-08-24T16:23:49.970Z", "revokedAt": "2025-08-24T16:23:49.970Z", "deletedAt": "2025-08-24T16:23:49.970Z" } ``` ### ApiKeyVerification - **Type:**`object` API key verification result with user information - **`apiKeyUuid` (required)** `string`, format: `uuid` — UUID of the verified API key - **`user` (required)** `object` — User information associated with the API key - **`valid` (required)** `boolean` — Whether the API key is valid and active **Example:** ``` { "valid": true, "user": { "uuid": "b3b3b3b3-b3b3-4b3b-b3b3-b3b3b3b3b3b3", "email": "user@example.com", "name": "John Doe", "avatarUrl": "https://example.com/avatar.png", "createdAt": "2025-08-24T16:23:49.971Z", "updatedAt": "2025-08-24T16:23:49.971Z", "providerIdentities": [ { "provider": "google", "providerUserId": "1234567890" } ] }, "apiKeyUuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" } ``` ### PricingTier - **Type:**`object` * **`apiKeyLimit` (required)** `number` * **`name` (required)** `string` * **`rateLimit` (required)** `number` * **`description`** `string | null` — Tier description * **`stripeProductId`** `string | null` **Example:** ``` { "name": "Pro", "description": "Professional tier with all features", "rateLimit": 1000, "apiKeyLimit": 20, "stripeProductId": "prod_Siqa3ELSbzL8yl" } ```