Getting started
1. Create a personal access token at Settings → API Tokens. A token belongs to one workspace and acts with your role there. API access needs a Solo, Team or Business plan; GET /api/v1/me works on every plan.
2. Send it as a bearer token:
curl -H 'Authorization: Bearer tta_YOUR_TOKEN' \
https://demo.trackingtabs.com/api/v1/me3. Requests and responses are JSON. Lists return { "data": [...], "total", "limit", "offset" }; single records are returned as the object itself; deletes return 204. Errors always look like { "error": { "code", "message", "details"? } }.
Access. Members see and change only their own time entries and only projects that aren't restricted to other people. Admins and owners see the whole workspace; creating or changing projects, clients and webhooks, and deleting tags, tasks and invoices, needs admin or owner.
Rate limit. 600 requests per hour per token. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds); a 429 adds Retry-After.
CORS. The API allows any origin (auth is the bearer token, never a cookie), so browser apps and extensions can call it directly. Never ship a token in a public web page.
Retries. POST /api/v1/entries accepts an idempotency_key (or an Idempotency-Key header); repeating it returns the original entry with 200.
Webhook deliveries
Events: time_entry.created, time_entry.updated, time_entry.deleted, project.created, project.updated, project.deleted, client.created, client.updated, client.deleted. They fire for changes made through the API.
Each delivery is a POST with JSON { "event", "created_at", "data" }, where data is the record in the same shape the API returns. Headers: X-Webhook-Event, User-Agent: TrackingTabs-Webhooks/1.0 and X-Signature: sha256=<hex>, the HMAC-SHA256 of the raw body keyed with the webhook's secret (shown once when you create it). Compare with a constant-time check. A non-2xx answer is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours (6 attempts in all). URLs on private or internal networks are rejected.
// Node.js
import { createHmac, timingSafeEqual } from 'node:crypto'
const expected = 'sha256=' + createHmac('sha256', SECRET).update(rawBody).digest('hex')
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['x-signature']))Auth
/api/v1/meGet the authenticated user and workspace
Returns the user and workspace the bearer token belongs to. Works on every plan, so clients can use it to verify a token and show whether the plan includes API access.
Plan: Any plan
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/me' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string",
"format": "email"
},
"full_name": {
"type": "string",
"nullable": true
},
"timezone": {
"type": "string"
}
},
"required": [
"id",
"email",
"full_name",
"timezone"
],
"additionalProperties": false
},
"workspace": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"plan": {
"type": "string",
"enum": [
"free",
"solo",
"team",
"business"
]
},
"role": {
"type": "string",
"enum": [
"owner",
"admin",
"member"
]
},
"api_access": {
"type": "boolean",
"description": "Whether the plan includes API access"
}
},
"required": [
"id",
"name",
"slug",
"plan",
"role",
"api_access"
],
"additionalProperties": false
}
},
"required": [
"user",
"workspace"
],
"additionalProperties": false
}Entries
/api/v1/entriesList time entries
Returns time entries in the token's workspace, newest first by `start`. Members see only their own entries; admins and owners see everyone's and can filter by `user_id`.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| from | query | date-time | Inclusive lower bound on `start`. |
| to | query | date-time | Exclusive upper bound on `start`. |
| project_id | query | uuid | Only this project. |
| task_id | query | uuid | Only this task. |
| client_id | query | uuid | Only entries on projects of this client. |
| tag | query | string | Only entries carrying this tag name. |
| billable | query | "true" | "false" | `true` for billable entries only, `false` for non-billable only. |
| running | query | "true" | "false" | `true` for running timers only, `false` for completed entries only. |
| user_id | query | uuid | Only this user (admins/owners; ignored for members). |
| limit | query | integer (1–200) = 50 | Page size (default 50, max 200). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/entries' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}
},
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"limit",
"offset"
],
"additionalProperties": false
}/api/v1/entriesCreate a time entry
Creates a time entry for the token owner. If `stop` is omitted the entry is a running timer, and a timer already running in this workspace is stopped at the new entry's `start` (409 if the user's timer is running in another workspace — there is one running timer per user). Completed entries may not overlap another entry of the same user (409). Pass `idempotency_key` (or an `Idempotency-Key` header) to retry safely: a repeated key returns the original entry with status 200.
Plan: Solo, Team or Business
Request body
{
"description": "Drafting Q2 retainer renewal",
"project_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
"tags": [
"client-work",
"writing"
],
"start": "2026-05-24T14:00:00Z",
"stop": "2026-05-24T15:30:00Z",
"billable": true,
"idempotency_key": "renewal-draft-2026-05-24"
}Body schema
{
"type": "object",
"properties": {
"description": {
"type": "string",
"maxLength": 2000,
"default": ""
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true,
"description": "A task implies its project"
},
"tags": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 64
},
"maxItems": 20,
"description": "Tag names. Missing tags are created in the workspace."
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "Omit to create a running timer",
"nullable": true
},
"billable": {
"type": "boolean",
"description": "Defaults to the project's billable flag, else the workspace default"
},
"idempotency_key": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Retry-safe key; also accepted as the Idempotency-Key header"
}
},
"required": [
"start"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/entries' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"description":"Drafting Q2 retainer renewal","project_id":"5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456","tags":["client-work","writing"],"start":"2026-05-24T14:00:00Z","stop":"2026-05-24T15:30:00Z","billable":true,"idempotency_key":"renewal-draft-2026-05-24"}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/entries/currentGet the running timer
Returns the token owner's running entry in this workspace, or `null` when no timer is running.
Plan: Solo, Team or Business
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/entries/current' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false,
"nullable": true
}
},
"required": [
"data"
],
"additionalProperties": false
}/api/v1/entries/startStart a timer
Starts a timer now for the token owner. A timer already running in this workspace is stopped first. There is one running timer per user, so a timer running in another workspace returns 409.
Plan: Solo, Team or Business
Request body (optional)
{
"description": "Code review",
"project_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
"tags": [
"review"
]
}Body schema
{
"type": "object",
"properties": {
"description": {
"type": "string",
"maxLength": 2000,
"default": ""
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 64
},
"maxItems": 20,
"description": "Tag names. Missing tags are created in the workspace."
},
"billable": {
"type": "boolean"
}
},
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/entries/start' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"description":"Code review","project_id":"5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456","tags":["review"]}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/entries/stopStop the running timer
Stops the token owner's running entry in this workspace. Returns 404 if no timer is running.
Plan: Solo, Team or Business
Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/entries/stop' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/entries/{id}Get a time entry
Members can read only their own entries; admins and owners can read any entry in the workspace.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Entry ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/entries/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/entries/{id}Update a time entry
Patches fields on an entry. Members can update only their own entries; admins and owners can update any entry in the workspace. `tags` replaces the entry's tags. Setting `stop` to `null` is not allowed on a completed entry; start a timer instead.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Entry ID. |
Request body
{
"description": "Drafting Q2 retainer renewal (revised)",
"billable": true
}Body schema
{
"type": "object",
"properties": {
"description": {
"type": "string",
"maxLength": 2000
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 64
},
"maxItems": 20,
"description": "Replaces the entry's tags"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"billable": {
"type": "boolean"
}
},
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/entries/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"description":"Drafting Q2 retainer renewal (revised)","billable":true}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"description": {
"type": "string"
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "`null` while the timer is running",
"nullable": true
},
"duration_seconds": {
"type": "integer",
"nullable": true
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Rate snapshot taken when the entry was created"
},
"currency": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag names"
},
"source": {
"type": "string",
"description": "Where the entry came from: web, api or import"
},
"idempotency_key": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"user_id",
"project_id",
"task_id",
"description",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"currency",
"tags",
"source",
"idempotency_key",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/entries/{id}Delete a time entry
Deletes an entry permanently. Same access rules as update.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Entry ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/entries/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
Projects
/api/v1/projectsList projects
Returns projects visible to the token owner, ordered by name. If a project has explicit members, only those members (plus admins and owners) see it.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| client_id | query | uuid | Only this client's projects. |
| archived | query | "true" | "false" | `true` to include archived projects (default `false`). |
| limit | query | integer (1–1000) = 500 | Page size (default 500, max 1000). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/projects' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"name": {
"type": "string"
},
"color": {
"type": "string"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true
},
"currency": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"name",
"color",
"billable",
"hourly_rate",
"currency",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}
},
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"limit",
"offset"
],
"additionalProperties": false
}/api/v1/projectsCreate a project
Creates a project. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Request body
{
"name": "Q2 Retainer",
"client_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
"color": "#3B82F6",
"billable": true,
"hourly_rate": 175,
"currency": "USD"
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"minimum": 0,
"nullable": true
},
"currency": {
"type": "string",
"minLength": 3,
"maxLength": 3,
"description": "ISO 4217 currency code, e.g. USD"
}
},
"required": [
"name"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/projects' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name":"Q2 Retainer","client_id":"5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456","color":"#3B82F6","billable":true,"hourly_rate":175,"currency":"USD"}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"name": {
"type": "string"
},
"color": {
"type": "string"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true
},
"currency": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"name",
"color",
"billable",
"hourly_rate",
"currency",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/projects/{id}Get a project
Returns one project, subject to the same visibility rules as the list.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Project ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/projects/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"name": {
"type": "string"
},
"color": {
"type": "string"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true
},
"currency": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"name",
"color",
"billable",
"hourly_rate",
"currency",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/projects/{id}Update or archive a project
Patches a project; set `archived` to archive or restore it. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Project ID. |
Request body
{
"hourly_rate": 190,
"archived": false
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"minimum": 0,
"nullable": true
},
"currency": {
"type": "string",
"minLength": 3,
"maxLength": 3,
"description": "ISO 4217 currency code, e.g. USD"
},
"archived": {
"type": "boolean"
}
},
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/projects/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"hourly_rate":190,"archived":false}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"name": {
"type": "string"
},
"color": {
"type": "string"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true
},
"currency": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"name",
"color",
"billable",
"hourly_rate",
"currency",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/projects/{id}Delete a project
Deletes a project and its tasks. Time entries are kept and lose their project. Prefer archiving. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Project ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/projects/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
Clients
/api/v1/clientsList clients
Returns clients in the workspace, ordered by name.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| archived | query | "true" | "false" | `true` to include archived clients (default `false`). |
| limit | query | integer (1–1000) = 500 | Page size (default 500, max 1000). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/clients' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}
},
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"limit",
"offset"
],
"additionalProperties": false
}/api/v1/clientsCreate a client
Creates a client. Names are unique per workspace. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Request body
{
"name": "LVC Beverly Hills"
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": [
"name"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/clients' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name":"LVC Beverly Hills"}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/clients/{id}Get a client
Returns one client.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Client ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/clients/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/clients/{id}Rename or archive a client
Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Client ID. |
Request body
{
"archived": true
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"archived": {
"type": "boolean"
}
},
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/clients/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"archived":true}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"archived",
"created_at",
"updated_at"
],
"additionalProperties": false
}/api/v1/clients/{id}Delete a client
Deletes a client. Its projects are kept and lose their client. Prefer archiving. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Client ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/clients/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
Tags
/api/v1/tagsCreate a tag
Creates a tag. If a tag with that name exists, it is returned with status 200.
Plan: Solo, Team or Business
Request body
{
"name": "client-work"
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 64
}
},
"required": [
"name"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/tags' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name":"client-work"}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"created_at"
],
"additionalProperties": false
}200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"created_at"
],
"additionalProperties": false
}/api/v1/tags/{id}Rename a tag
Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Tag ID. |
Request body
{
"name": "client"
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 64
}
},
"required": [
"name"
],
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/tags/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name":"client"}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"name",
"created_at"
],
"additionalProperties": false
}/api/v1/tags/{id}Delete a tag
Removes the tag from all entries. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Tag ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/tags/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
Tasks
/api/v1/tasksList tasks
Returns tasks in the workspace, optionally for one project, ordered by name.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| project_id | query | uuid | Only this project's tasks. |
| archived | query | "true" | "false" | `true` to include archived tasks (default `false`). |
| limit | query | integer (1–1000) = 500 | Page size (default 500, max 1000). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/tasks' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"estimated_seconds": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"project_id",
"name",
"archived",
"estimated_seconds",
"created_at"
],
"additionalProperties": false
}
},
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"limit",
"offset"
],
"additionalProperties": false
}/api/v1/tasksCreate a task
Creates a task under a project.
Plan: Solo, Team or Business
Request body
{
"project_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
"name": "Design review",
"estimated_seconds": 7200
}Body schema
{
"type": "object",
"properties": {
"project_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"estimated_seconds": {
"type": "integer",
"minimum": 0,
"nullable": true
}
},
"required": [
"project_id",
"name"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/tasks' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"project_id":"5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456","name":"Design review","estimated_seconds":7200}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"estimated_seconds": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"project_id",
"name",
"archived",
"estimated_seconds",
"created_at"
],
"additionalProperties": false
}/api/v1/tasks/{id}Get a task
Returns one task.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Task ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/tasks/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"estimated_seconds": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"project_id",
"name",
"archived",
"estimated_seconds",
"created_at"
],
"additionalProperties": false
}/api/v1/tasks/{id}Update or archive a task
Patches a task's name, estimate or archived flag.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Task ID. |
Request body
{
"archived": true
}Body schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"estimated_seconds": {
"type": "integer",
"minimum": 0,
"nullable": true
},
"archived": {
"type": "boolean"
}
},
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/tasks/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"archived":true}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"project_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"archived": {
"type": "boolean"
},
"estimated_seconds": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"project_id",
"name",
"archived",
"estimated_seconds",
"created_at"
],
"additionalProperties": false
}/api/v1/tasks/{id}Delete a task
Deletes a task; entries keep their project and lose the task. Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Task ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/tasks/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
Members
/api/v1/membersList workspace members
Returns everyone in the workspace with their role. `hourly_rate` is only filled in for admins and owners.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| limit | query | integer (1–1000) = 500 | Page size (default 500, max 1000). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/members' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string"
},
"full_name": {
"type": "string",
"nullable": true
},
"role": {
"type": "string",
"enum": [
"owner",
"admin",
"member"
]
},
"joined_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"hourly_rate": {
"type": "number",
"nullable": true,
"description": "Member billing rate; only returned to admins and owners (null otherwise)"
}
},
"required": [
"user_id",
"email",
"full_name",
"role",
"joined_at",
"hourly_rate"
],
"additionalProperties": false
}
},
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"limit",
"offset"
],
"additionalProperties": false
}Reports
/api/v1/reports/summarySummary report
Totals for completed entries in the range, grouped by one dimension. Amounts use each entry's rate snapshot; `currency` is the workspace default. Members get their own time only.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| from* | query | date or date-time | Start of the range. A date is the start of that day in `timezone`; a timestamp is used as-is (inclusive). |
| to* | query | date or date-time | End of the range. A date includes that whole day in `timezone`; a timestamp is exclusive. |
| timezone | query | string | IANA timezone for date bounds and per-day grouping. Defaults to the token owner's profile timezone. |
| project_id | query | uuid[] | Only these projects. Repeat the parameter for several. |
| client_id | query | uuid[] | Only projects of these clients. Repeatable. |
| tag_id | query | uuid[] | Only entries with at least one of these tags. Repeatable. |
| user_id | query | uuid[] | Only these users (admins/owners; members always see only their own time). Repeatable. |
| billable | query | "true" | "false" | `true` for billable entries only, `false` for non-billable only. |
| description | query | string | Case-insensitive substring match on the entry description. |
| group_by | query | "project" | "client" | "user" | "task" | "tag" | "description" = "project" | Grouping dimension (default `project`). With `tag`, an entry counts once per tag. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/reports/summary?from=2026-05-01&to=2026-05-31' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"from": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"to": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"timezone": {
"type": "string"
},
"group_by": {
"type": "string",
"enum": [
"project",
"client",
"user",
"task",
"tag",
"description"
]
},
"total_seconds": {
"type": "integer"
},
"billable_seconds": {
"type": "integer"
},
"billable_amount": {
"type": "number"
},
"currency": {
"type": "string"
},
"groups": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Group id, or `none` for entries without one"
},
"label": {
"type": "string"
},
"color": {
"type": "string"
},
"seconds": {
"type": "integer"
},
"billable_seconds": {
"type": "integer"
},
"amount": {
"type": "number"
}
},
"required": [
"key",
"label",
"seconds",
"billable_seconds",
"amount"
],
"additionalProperties": false
}
}
},
"required": [
"from",
"to",
"timezone",
"group_by",
"total_seconds",
"billable_seconds",
"billable_amount",
"currency",
"groups"
],
"additionalProperties": false
}/api/v1/reports/detailedDetailed report
Completed entries in the range with project, client, task, user and amount resolved, newest first. Paginated; `total_seconds` covers the whole range, not just the page.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| from* | query | date or date-time | Start of the range. A date is the start of that day in `timezone`; a timestamp is used as-is (inclusive). |
| to* | query | date or date-time | End of the range. A date includes that whole day in `timezone`; a timestamp is exclusive. |
| timezone | query | string | IANA timezone for date bounds and per-day grouping. Defaults to the token owner's profile timezone. |
| project_id | query | uuid[] | Only these projects. Repeat the parameter for several. |
| client_id | query | uuid[] | Only projects of these clients. Repeatable. |
| tag_id | query | uuid[] | Only entries with at least one of these tags. Repeatable. |
| user_id | query | uuid[] | Only these users (admins/owners; members always see only their own time). Repeatable. |
| billable | query | "true" | "false" | `true` for billable entries only, `false` for non-billable only. |
| description | query | string | Case-insensitive substring match on the entry description. |
| limit | query | integer (1–500) = 100 | Page size (default 100, max 500). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/reports/detailed?from=2026-05-01&to=2026-05-31' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Local date of `start` in the report timezone"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"user_name": {
"type": "string"
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"project_name": {
"type": "string",
"nullable": true
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client_name": {
"type": "string",
"nullable": true
},
"task_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"task_name": {
"type": "string",
"nullable": true
},
"description": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"start": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"stop": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"duration_seconds": {
"type": "integer"
},
"billable": {
"type": "boolean"
},
"hourly_rate": {
"type": "number",
"nullable": true
},
"amount": {
"type": "number",
"nullable": true
},
"currency": {
"type": "string"
}
},
"required": [
"id",
"date",
"user_id",
"user_name",
"project_id",
"project_name",
"client_id",
"client_name",
"task_id",
"task_name",
"description",
"tags",
"start",
"stop",
"duration_seconds",
"billable",
"hourly_rate",
"amount",
"currency"
],
"additionalProperties": false
}
},
"total": {
"type": "integer"
},
"total_seconds": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"total_seconds",
"limit",
"offset"
],
"additionalProperties": false
}/api/v1/reports/weeklyWeekly (timesheet) report
Seconds per day for each project or user, with daily and grand totals. Days are local dates in `timezone`. The range may span up to 92 days.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| from* | query | date or date-time | Start of the range. A date is the start of that day in `timezone`; a timestamp is used as-is (inclusive). |
| to* | query | date or date-time | End of the range. A date includes that whole day in `timezone`; a timestamp is exclusive. |
| timezone | query | string | IANA timezone for date bounds and per-day grouping. Defaults to the token owner's profile timezone. |
| project_id | query | uuid[] | Only these projects. Repeat the parameter for several. |
| client_id | query | uuid[] | Only projects of these clients. Repeatable. |
| tag_id | query | uuid[] | Only entries with at least one of these tags. Repeatable. |
| user_id | query | uuid[] | Only these users (admins/owners; members always see only their own time). Repeatable. |
| billable | query | "true" | "false" | `true` for billable entries only, `false` for non-billable only. |
| description | query | string | Case-insensitive substring match on the entry description. |
| group_by | query | "project" | "user" = "project" | Row dimension (default `project`). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/reports/weekly?from=2026-05-01&to=2026-05-31' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"timezone": {
"type": "string"
},
"group_by": {
"type": "string",
"enum": [
"project",
"user"
]
},
"days": {
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
}
},
"rows": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"color": {
"type": "string"
},
"by_day": {
"type": "object",
"additionalProperties": {
"type": "integer"
},
"description": "Seconds per day, keyed by YYYY-MM-DD"
},
"total_seconds": {
"type": "integer"
}
},
"required": [
"key",
"label",
"by_day",
"total_seconds"
],
"additionalProperties": false
}
},
"totals": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
},
"total_seconds": {
"type": "integer"
}
},
"required": [
"timezone",
"group_by",
"days",
"rows",
"totals",
"total_seconds"
],
"additionalProperties": false
}Invoices
/api/v1/invoicesList invoices
Returns invoices in the workspace, newest issue date first.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| status | query | "draft" | "sent" | "paid" | "void" | Only invoices in this status. |
| client_id | query | uuid | Only this client's invoices. |
| from | query | date | Issue date on or after. |
| to | query | date | Issue date on or before. |
| limit | query | integer (1–200) = 50 | Page size (default 50, max 200). |
| offset | query | integer (0–) = 0 | Number of records to skip (default 0). |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/invoices' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"additionalProperties": false,
"nullable": true
},
"number": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"sent",
"paid",
"void"
]
},
"currency": {
"type": "string"
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"tax_rate_pct": {
"type": "number"
},
"discount_pct": {
"type": "number"
},
"markup_pct": {
"type": "number"
},
"subtotal_cents": {
"type": "integer"
},
"tax_cents": {
"type": "integer"
},
"discount_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
},
"sent_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_via": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"number",
"status",
"currency",
"issue_date",
"due_date",
"notes",
"recipient_email",
"line_items",
"tax_rate_pct",
"discount_pct",
"markup_pct",
"subtotal_cents",
"tax_cents",
"discount_cents",
"total_cents",
"sent_at",
"paid_at",
"paid_via",
"created_at"
],
"additionalProperties": true
}
},
"total": {
"type": "integer"
},
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
}
},
"required": [
"data",
"total",
"limit",
"offset"
],
"additionalProperties": false
}/api/v1/invoicesCreate an invoice
Creates an invoice (draft by default). Line-item amounts are in cents; totals, tax and the invoice number are computed from the workspace invoice settings. Use `POST /api/v1/invoices/from-entries` to build line items from billable time.
Plan: Solo, Team or Business
Request body
{
"client_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
"line_items": [
{
"description": "Design work",
"quantity": 12.5,
"unit": "hr",
"rate_cents": 17500
}
],
"due_date": "2026-06-30"
}Body schema
{
"type": "object",
"properties": {
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"number": {
"type": "string",
"minLength": 1,
"maxLength": 64
},
"currency": {
"type": "string",
"minLength": 3,
"maxLength": 3
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"format": "email",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
},
"default": []
},
"tax_rate_pct": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"discount_pct": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"markup_pct": {
"type": "number",
"minimum": 0,
"maximum": 100
}
},
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/invoices' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"client_id":"5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456","line_items":[{"description":"Design work","quantity":12.5,"unit":"hr","rate_cents":17500}],"due_date":"2026-06-30"}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"additionalProperties": false,
"nullable": true
},
"number": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"sent",
"paid",
"void"
]
},
"currency": {
"type": "string"
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"tax_rate_pct": {
"type": "number"
},
"discount_pct": {
"type": "number"
},
"markup_pct": {
"type": "number"
},
"subtotal_cents": {
"type": "integer"
},
"tax_cents": {
"type": "integer"
},
"discount_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
},
"sent_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_via": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"number",
"status",
"currency",
"issue_date",
"due_date",
"notes",
"recipient_email",
"line_items",
"tax_rate_pct",
"discount_pct",
"markup_pct",
"subtotal_cents",
"tax_cents",
"discount_cents",
"total_cents",
"sent_at",
"paid_at",
"paid_via",
"created_at"
],
"additionalProperties": true
}/api/v1/invoices/from-entriesBuild invoice line items from time
Groups billable, completed entries in the range (optionally for one client) into line items by project and rate. Nothing is saved; pass the returned `line_items` to `POST /api/v1/invoices`.
Plan: Solo, Team or Business
Request body
{
"client_id": "5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456",
"from": "2026-05-01",
"to": "2026-05-31"
}Body schema
{
"type": "object",
"properties": {
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"from": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
{
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
],
"description": "A date (YYYY-MM-DD, interpreted in the report timezone) or an ISO 8601 timestamp"
},
"to": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
{
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
],
"description": "Inclusive; a date covers the whole day"
}
},
"required": [
"from",
"to"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/invoices/from-entries' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"client_id":"5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456","from":"2026-05-01","to":"2026-05-31"}'Responses
200 response schema
{
"type": "object",
"properties": {
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"entry_count": {
"type": "integer"
},
"total_hours": {
"type": "number"
}
},
"required": [
"line_items",
"entry_count",
"total_hours"
],
"additionalProperties": false
}/api/v1/invoices/{id}Get an invoice
Returns one invoice with its client.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Invoice ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/invoices/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"additionalProperties": false,
"nullable": true
},
"number": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"sent",
"paid",
"void"
]
},
"currency": {
"type": "string"
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"tax_rate_pct": {
"type": "number"
},
"discount_pct": {
"type": "number"
},
"markup_pct": {
"type": "number"
},
"subtotal_cents": {
"type": "integer"
},
"tax_cents": {
"type": "integer"
},
"discount_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
},
"sent_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_via": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"number",
"status",
"currency",
"issue_date",
"due_date",
"notes",
"recipient_email",
"line_items",
"tax_rate_pct",
"discount_pct",
"markup_pct",
"subtotal_cents",
"tax_cents",
"discount_cents",
"total_cents",
"sent_at",
"paid_at",
"paid_via",
"created_at"
],
"additionalProperties": true
}/api/v1/invoices/{id}Update an invoice
Patches an invoice; totals are recomputed.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Invoice ID. |
Request body
{
"notes": "Net 15"
}Body schema
{
"type": "object",
"properties": {
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"number": {
"type": "string",
"minLength": 1,
"maxLength": 64
},
"currency": {
"type": "string",
"minLength": 3,
"maxLength": 3
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"format": "email",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
},
"default": []
},
"tax_rate_pct": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"discount_pct": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"markup_pct": {
"type": "number",
"minimum": 0,
"maximum": 100
}
},
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/invoices/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"notes":"Net 15"}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"additionalProperties": false,
"nullable": true
},
"number": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"sent",
"paid",
"void"
]
},
"currency": {
"type": "string"
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"tax_rate_pct": {
"type": "number"
},
"discount_pct": {
"type": "number"
},
"markup_pct": {
"type": "number"
},
"subtotal_cents": {
"type": "integer"
},
"tax_cents": {
"type": "integer"
},
"discount_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
},
"sent_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_via": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"number",
"status",
"currency",
"issue_date",
"due_date",
"notes",
"recipient_email",
"line_items",
"tax_rate_pct",
"discount_pct",
"markup_pct",
"subtotal_cents",
"tax_cents",
"discount_cents",
"total_cents",
"sent_at",
"paid_at",
"paid_via",
"created_at"
],
"additionalProperties": true
}/api/v1/invoices/{id}Delete an invoice
Requires the admin or owner role.
Plan: Solo, Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Invoice ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/invoices/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
/api/v1/invoices/{id}/pdfDownload an invoice PDF
Renders the invoice as a PDF.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Invoice ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/invoices/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456/pdf' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
application/pdf/api/v1/invoices/{id}/sendEmail an invoice
Emails the invoice PDF to `to` (or the invoice's recipient) and marks it sent. This sends real email.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Invoice ID. |
Request body (optional)
{
"to": "billing@client.com"
}Body schema
{
"type": "object",
"properties": {
"to": {
"type": "string",
"format": "email",
"description": "Defaults to the invoice's recipient_email"
}
},
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/invoices/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456/send' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"to":"billing@client.com"}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"additionalProperties": false,
"nullable": true
},
"number": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"sent",
"paid",
"void"
]
},
"currency": {
"type": "string"
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"tax_rate_pct": {
"type": "number"
},
"discount_pct": {
"type": "number"
},
"markup_pct": {
"type": "number"
},
"subtotal_cents": {
"type": "integer"
},
"tax_cents": {
"type": "integer"
},
"discount_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
},
"sent_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_via": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"number",
"status",
"currency",
"issue_date",
"due_date",
"notes",
"recipient_email",
"line_items",
"tax_rate_pct",
"discount_pct",
"markup_pct",
"subtotal_cents",
"tax_cents",
"discount_cents",
"total_cents",
"sent_at",
"paid_at",
"paid_via",
"created_at"
],
"additionalProperties": true
}/api/v1/invoices/{id}/mark-paidMark an invoice paid
Sets status `paid` and records `paid_at` (and `paid_via` when given).
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Invoice ID. |
Request body (optional)
{
"paid_via": "ACH"
}Body schema
{
"type": "object",
"properties": {
"paid_via": {
"type": "string",
"maxLength": 120
}
},
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/invoices/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456/mark-paid' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"paid_via":"ACH"}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workspace_id": {
"type": "string",
"format": "uuid"
},
"client_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"additionalProperties": false,
"nullable": true
},
"number": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"sent",
"paid",
"void"
]
},
"currency": {
"type": "string"
},
"issue_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD"
},
"due_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Calendar date, YYYY-MM-DD",
"nullable": true
},
"notes": {
"type": "string",
"nullable": true
},
"recipient_email": {
"type": "string",
"nullable": true
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"description": {
"type": "string",
"minLength": 1
},
"quantity": {
"type": "number",
"minimum": 0
},
"unit": {
"type": "string",
"default": "hr"
},
"rate_cents": {
"type": "integer",
"minimum": 0
},
"amount_cents": {
"type": "integer",
"minimum": 0
},
"project_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"time_entry_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": [
"description",
"quantity",
"rate_cents"
],
"additionalProperties": false
}
},
"tax_rate_pct": {
"type": "number"
},
"discount_pct": {
"type": "number"
},
"markup_pct": {
"type": "number"
},
"subtotal_cents": {
"type": "integer"
},
"tax_cents": {
"type": "integer"
},
"discount_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
},
"sent_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"paid_via": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"workspace_id",
"client_id",
"number",
"status",
"currency",
"issue_date",
"due_date",
"notes",
"recipient_email",
"line_items",
"tax_rate_pct",
"discount_pct",
"markup_pct",
"subtotal_cents",
"tax_cents",
"discount_cents",
"total_cents",
"sent_at",
"paid_at",
"paid_via",
"created_at"
],
"additionalProperties": true
}Webhooks
/api/v1/webhooksList webhooks
Requires the admin or owner role and a Team or Business plan.
Plan: Team or Business · Role: admin or owner
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/webhooks' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"time_entry.created",
"time_entry.updated",
"time_entry.deleted",
"project.created",
"project.updated",
"project.deleted",
"client.created",
"client.updated",
"client.deleted"
]
}
},
"active": {
"type": "boolean"
},
"last_delivery_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"last_delivery_status": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"url",
"events",
"active",
"last_delivery_at",
"last_delivery_status",
"created_at"
],
"additionalProperties": false
}
}
},
"required": [
"data"
],
"additionalProperties": false
}/api/v1/webhooksCreate a webhook
Subscribes a URL to events. The response includes the signing `secret` once; store it to verify the `X-Signature` header (`sha256=` + HMAC-SHA256 of the raw body).
Plan: Team or Business · Role: admin or owner
Request body
{
"url": "https://example.com/hooks/tracking",
"events": [
"time_entry.created",
"time_entry.updated"
]
}Body schema
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"time_entry.created",
"time_entry.updated",
"time_entry.deleted",
"project.created",
"project.updated",
"project.deleted",
"client.created",
"client.updated",
"client.deleted"
]
},
"minItems": 1
},
"active": {
"type": "boolean",
"default": true
}
},
"required": [
"url",
"events"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/webhooks' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/hooks/tracking","events":["time_entry.created","time_entry.updated"]}'Responses
201 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"time_entry.created",
"time_entry.updated",
"time_entry.deleted",
"project.created",
"project.updated",
"project.deleted",
"client.created",
"client.updated",
"client.deleted"
]
}
},
"active": {
"type": "boolean"
},
"last_delivery_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"last_delivery_status": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
},
"secret": {
"type": "string",
"description": "HMAC signing secret. Returned only when the webhook is created."
}
},
"required": [
"id",
"url",
"events",
"active",
"last_delivery_at",
"last_delivery_status",
"created_at",
"secret"
],
"additionalProperties": false
}/api/v1/webhooks/{id}Get a webhook
Requires the admin or owner role and a Team or Business plan.
Plan: Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Webhook ID. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/webhooks/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"time_entry.created",
"time_entry.updated",
"time_entry.deleted",
"project.created",
"project.updated",
"project.deleted",
"client.created",
"client.updated",
"client.deleted"
]
}
},
"active": {
"type": "boolean"
},
"last_delivery_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"last_delivery_status": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"url",
"events",
"active",
"last_delivery_at",
"last_delivery_status",
"created_at"
],
"additionalProperties": false
}/api/v1/webhooks/{id}Update a webhook
Change the URL, events or active flag.
Plan: Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Webhook ID. |
Request body
{
"active": false
}Body schema
{
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 2000
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"time_entry.created",
"time_entry.updated",
"time_entry.deleted",
"project.created",
"project.updated",
"project.deleted",
"client.created",
"client.updated",
"client.deleted"
]
},
"minItems": 1
},
"active": {
"type": "boolean"
}
},
"additionalProperties": false
}Example request
curl -X PATCH 'https://demo.trackingtabs.com/api/v1/webhooks/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"active":false}'Responses
200 response schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"time_entry.created",
"time_entry.updated",
"time_entry.deleted",
"project.created",
"project.updated",
"project.deleted",
"client.created",
"client.updated",
"client.deleted"
]
}
},
"active": {
"type": "boolean"
},
"last_delivery_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z",
"nullable": true
},
"last_delivery_status": {
"type": "integer",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp with timezone, e.g. 2026-05-24T18:00:00Z"
}
},
"required": [
"id",
"url",
"events",
"active",
"last_delivery_at",
"last_delivery_status",
"created_at"
],
"additionalProperties": false
}/api/v1/webhooks/{id}Delete a webhook
Stops all future deliveries.
Plan: Team or Business · Role: admin or owner
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | uuid | Webhook ID. |
Example request
curl -X DELETE 'https://demo.trackingtabs.com/api/v1/webhooks/5b2e1c4d-6f8a-4b3e-9c7d-abcdef123456' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
Import & export
/api/v1/export/entries.csvExport entries as CSV
CSV of time entries (members: their own; admins: everyone's), newest first. Cells that start with =, +, - or @ are prefixed with ' so spreadsheets don't run them as formulas.
Plan: Solo, Team or Business
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| from | query | date-time | Inclusive lower bound on `start`. |
| to | query | date-time | Inclusive upper bound on `start`. |
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/export/entries.csv' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
text/csv/api/v1/export/workspace.zipExport the workspace as a ZIP
ZIP of JSON files: workspace, projects, clients, tasks, tags, entries and, for admins, members. Members get only their own entries and only projects (and tasks) they can see.
Plan: Solo, Team or Business
Example request
curl -X GET 'https://demo.trackingtabs.com/api/v1/export/workspace.zip' \
-H 'Authorization: Bearer tta_YOUR_TOKEN'Responses
application/zip/api/v1/import/csvParse a CSV for import
Parses a Toggl, Harvest or generic CSV and returns the parsed entries plus the projects and clients that would be created. Nothing is saved; send `allEntries` to `POST /api/v1/import/commit`.
Plan: Solo, Team or Business
Request body
{
"source": "toggl",
"file": "<base64 CSV>"
}Body schema
{
"type": "object",
"properties": {
"source": {
"type": "string",
"enum": [
"toggl",
"harvest",
"generic"
]
},
"file": {
"type": "string",
"minLength": 1,
"description": "The CSV file, base64-encoded"
},
"mapping": {
"type": "object",
"additionalProperties": {
"type": "string",
"nullable": true
},
"description": "Column mapping; required for `generic` CSVs"
}
},
"required": [
"source",
"file"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/import/csv' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"source":"toggl","file":"<base64 CSV>"}'Responses
200 response schema
{
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"preview": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"projectName": {
"type": "string"
},
"clientName": {
"type": "string"
},
"start": {
"type": "string"
},
"stop": {
"type": "string"
},
"durationSeconds": {
"type": "number"
},
"billable": {
"type": "boolean"
},
"tagNames": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"description",
"projectName",
"clientName",
"start",
"stop",
"durationSeconds",
"billable",
"tagNames"
],
"additionalProperties": false
}
},
"allEntries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"projectName": {
"type": "string"
},
"clientName": {
"type": "string"
},
"start": {
"type": "string"
},
"stop": {
"type": "string"
},
"durationSeconds": {
"type": "number"
},
"billable": {
"type": "boolean"
},
"tagNames": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"description",
"projectName",
"clientName",
"start",
"stop",
"durationSeconds",
"billable",
"tagNames"
],
"additionalProperties": false
}
},
"detectedColumns": {
"type": "array",
"items": {
"type": "string"
}
},
"newProjects": {
"type": "array",
"items": {
"type": "string"
}
},
"newClients": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"total",
"preview",
"allEntries",
"detectedColumns",
"newProjects",
"newClients"
],
"additionalProperties": false
}/api/v1/import/commitImport parsed entries
Creates up to 500 entries for the token owner, creating missing clients, projects and tags. Creating clients or projects requires the admin or owner role; a member whose rows name a missing (or hidden) client or project gets 403. Re-importing the same rows is skipped (idempotent).
Plan: Solo, Team or Business
Request body
{
"source": "toggl",
"entries": [
{
"description": "Planning",
"projectName": "Website",
"clientName": "Acme",
"start": "2026-05-01T14:00:00Z",
"stop": "2026-05-01T15:00:00Z",
"durationSeconds": 3600,
"billable": true,
"tagNames": [
"planning"
]
}
]
}Body schema
{
"type": "object",
"properties": {
"source": {
"type": "string"
},
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"projectName": {
"type": "string"
},
"clientName": {
"type": "string"
},
"start": {
"type": "string"
},
"stop": {
"type": "string"
},
"durationSeconds": {
"type": "number"
},
"billable": {
"type": "boolean"
},
"tagNames": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"description",
"projectName",
"clientName",
"start",
"stop",
"durationSeconds",
"billable",
"tagNames"
],
"additionalProperties": false
},
"maxItems": 500
}
},
"required": [
"source",
"entries"
],
"additionalProperties": false
}Example request
curl -X POST 'https://demo.trackingtabs.com/api/v1/import/commit' \
-H 'Authorization: Bearer tta_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"source":"toggl","entries":[{"description":"Planning","projectName":"Website","clientName":"Acme","start":"2026-05-01T14:00:00Z","stop":"2026-05-01T15:00:00Z","durationSeconds":3600,"billable":true,"tagNames":["planning"]}]}'Responses
201 response schema
{
"type": "object",
"properties": {
"inserted": {
"type": "integer"
},
"skipped": {
"type": "integer"
},
"failed": {
"type": "integer"
}
},
"required": [
"inserted",
"skipped",
"failed"
],
"additionalProperties": false
}Error codes
unauthorized401Missing, invalid, revoked or expired token, or the token owner left the workspaceforbidden403Your role cannot do this (admin or owner required)feature_gated403Your plan does not include this (API access needs Solo, Team or Business)not_found404No such record in this workspace (or not visible to you)validation_error400Body or query failed validation; `details.issues` lists each problemconflict409Duplicate name/number, overlapping entry, or a timer running elsewhererate_limited429Too many requests; wait for `Retry-After` secondsinternal_error500Unexpected server error50 endpoints