# Authentication and API keys

Source: https://www.tracktimer.app/docs/authentication

Create a workspace-bound API key and understand scopes, expiration, and request authentication.

Use a personal API key to call `https://www.tracktimer.app/api/v1`. Every endpoint requires `Authorization: Bearer YOUR_API_KEY`. Browser session cookies alone do not authenticate these routes, and there is no API-key query parameter.

## Create a key

1. Sign in and select the workspace the integration should access.
2. Open [Settings](https://www.tracktimer.app/app/settings). Use **Verify for sensitive changes** if needed: key creation and revocation require passkey verification within the last five minutes.
3. Under **Personal API keys**, enter a recognizable name and select **Create key**.
4. Copy the key when shown and store it in your integration's secret manager. The plaintext is shown only at creation.

Keys use the `tt_` prefix and expire after 365 days. Create a replacement before expiration, update the integration, then revoke the old key in Settings. The current interface does not offer custom expiration or a scope picker.

Examples use `$TRACKTIMER_API_KEY` as a placeholder for a secret injected into your shell environment. They contain no working credential. Keep keys out of client-side bundles, repositories, screenshots, and request logs.

## Workspace and user boundaries

A key is bound to its creating user and the workspace selected at creation. Switching workspaces in the website does not retarget the key. Each request checks the key and current workspace membership. Invalid bindings or missing membership are rejected.

Project discovery returns assigned, unarchived projects. Owners and admins can discover every active client in their workspace, including clients without projects; other members see clients with assigned projects. Time-entry history contains only the key user's entries in the bound workspace, including historical entries.

## Scopes

Keys created in Settings receive all five default scopes:

- `clients:read`: discover accessible clients.
- `projects:read`: discover accessible projects for a client.
- `projects:write`: create projects when the key owner is a workspace owner or admin. Existing keys retain their scopes; create a replacement key to enable this permission.
- `timers:read`: read the active timer and personal time-entry history.
- `timers:write`: start and stop timers.

The server checks the required scope on every request. A verified key missing it receives `403 INSUFFICIENT_SCOPE`. The public API does not provide client creation, project editing, time-entry editing, invoicing, or organization financial reports.

## Request and response basics

GET requests need no body. Starting a timer takes JSON with `Content-Type: application/json`. Timer POST endpoints require a nonblank `Idempotency-Key` of at most 255 characters after trimming. Persist a fresh unique operation identifier before each intended timer mutation; keep it unchanged when retrying that operation.

Successful v1 responses return HTTP 200 (201 for project creation) and JSON directly, with no `data` envelope. They include an `X-Request-Id` header. Error bodies carry their own `requestId`. All seven operations share a per-key limit of 120 requests per 60-second window. See [errors and retries](https://www.tracktimer.app/docs/errors-and-retries).

## First request

```sh
curl "https://www.tracktimer.app/api/v1/clients" \
  --header "Authorization: Bearer $TRACKTIMER_API_KEY"
```

Examples use illustrative IDs and data. Use the values returned by your own workspace. [Review error handling and retry behavior.](https://www.tracktimer.app/docs/errors-and-retries)
