API reference
Build on your time data: read and write projects, sessions, reports, clients and invoices, and receive signed webhooks.
API version 4.0.0
Introduction
The Temporal.ist API gives your scripts and tools the same data as the app: projects, sessions and timers, reports, clients, invoices and webhooks. It is a JSON API over HTTPS at:
https://temporal.ist/api/v2
The API is part of the Pro and Team plans. Everything below is generated from the API's own schema, which you can also download as OpenAPI.
Authentication
Create a personal API key in the app under Settings → Integrations. A key either reads, or reads and writes, and it works with your account in your current organisation. Its secret is shown once; store it like a password, and revoke the key in the same place when you no longer need it.
Send the key as a bearer token on every request:
Authorization: Bearer tk_live_…
A missing, revoked or mistyped key answers 401. A read-only key answers 403 for anything that changes data. Without a plan that includes the API, requests answer 402.
Quickstart
List your projects, then start a timer on one of them:
curl https://temporal.ist/api/v2/projects \
-H "Authorization: Bearer $TEMPORALIST_KEY"
curl -X POST https://temporal.ist/api/v2/sessions/start \
-H "Authorization: Bearer $TEMPORALIST_KEY" \
-H "Content-Type: application/json" \
-d '{"project_id": "<project id>"}'
Requests and responses
- JSON in and out, with
snake_casefield names. - Times are ISO 8601 instants with their offset, such as
2026-10-11T09:30:00+02:00. Day boundaries in reports follow your account's timezone. - Lists return
{"items": [...], "next_cursor": "..."}. Passnext_cursorback as?cursor=for the next page;?limit=takes up to 200 (default 50). The last page hasnext_cursor: null. - Retries are safe. Creating requests accept your own
id(a UUID). Sending the same request again returns the record that already exists instead of creating a second one. - Records you cannot see answer
404, whether they do not exist or belong to someone else.
Errors
Every error has the same shape:
{
"error": {
"code": "validation_error",
"message": "Some fields need attention.",
"fields": { "end_at": "End must be after the start." }
}
}
| Status | Meaning |
|---|---|
400 |
The request cannot be done as asked; code says why. |
401 |
The key is missing, revoked or wrong. |
402 |
Your plan does not include this. |
403 |
The key or your role is not allowed to do this. |
404 |
The record does not exist, or is not yours. |
409 |
It conflicts with the current state, such as a timer that is already running. |
422 |
A field is invalid; fields names it. |
429 |
Too many requests; wait and try again. |
Receiving webhooks
A webhook subscription sends a POST to your HTTPS address for each event you choose: project.created, session.created, session.closed, invoice.created and invoice.paid. Every delivery carries:
X-Temporalist-Event: session.closed
X-Temporalist-Delivery: <delivery id, the same on every retry>
X-Temporalist-Signature: t=<unix time>,v1=<hex HMAC-SHA256>
To check a delivery, compute an HMAC-SHA256 with your subscription's secret as the key over the timestamp, a dot and the raw request body, and compare it with v1:
import hashlib, hmac
def is_genuine(secret: str, header: str, body: bytes) -> bool:
parts = dict(item.split("=", 1) for item in header.split(","))
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
Answer with any 2xx status within 10 seconds. Failed deliveries are retried with growing delays, up to eight attempts, so the same event can arrive more than once: use X-Temporalist-Delivery to skip duplicates. Addresses must be public HTTPS hosts, and redirects are not followed.
Identity
Who the key belongs to: account, timezone, organisation role and plan features.
GET/api/v2/me
Get MeRead key
Bootstrap for web, desktop, CLI and extension. 401 when signed out.
- Returns
200MeOut
Projects
Projects you own or that your team shares with you. Names are labels; use the id to refer to a project.
GET/api/v2/projects
List ProjectsRead key
| Name | In | Type | Description |
|---|---|---|---|
cursor | query | string | null | |
limit | query | integer | Default: 50. |
status | query | "active" | "archived" | "all" | Default: "active". |
q | query | string | null | Case-insensitive substring of project or client name. |
client_id | query | string (uuid) | null | |
trackable | query | boolean | Only projects the caller may track on (own or team-assigned, active). Default: false. |
include_hidden | query | boolean | Default: true. |
include_stats | query | boolean | Default: false. |
sort | query | "name" | "recent" | `recent` = the caller's latest activity first. Default: "name". |
- Returns
200Page_ProjectOut_
POST/api/v2/projects
Create ProjectRead and write key
- Body
ProjectCreate- Returns
200ProjectOut
GET/api/v2/projects/{project_id}
Get ProjectRead key
| Name | In | Type | Description |
|---|---|---|---|
project_idrequired | path | string (uuid) |
- Returns
200ProjectOut
PATCH/api/v2/projects/{project_id}
Update ProjectRead and write key
| Name | In | Type | Description |
|---|---|---|---|
project_idrequired | path | string (uuid) |
- Body
ProjectUpdate- Returns
200ProjectOut
POST/api/v2/projects/{project_id}/archive
Archive ProjectRead and write key
| Name | In | Type | Description |
|---|---|---|---|
project_idrequired | path | string (uuid) |
- Returns
200ProjectOut
POST/api/v2/projects/{project_id}/unarchive
Unarchive ProjectRead and write key
| Name | In | Type | Description |
|---|---|---|---|
project_idrequired | path | string (uuid) |
- Returns
200ProjectOut
Sessions and timers
Your own tracked time. Durations are seconds of worked time with pauses taken out; instants carry their UTC offset.
GET/api/v2/sessions
List SessionsRead key
| Name | In | Type | Description |
|---|---|---|---|
cursor | query | string | null | |
limit | query | integer | Default: 50. |
from_date | query | string (date) | null | Default depends on the endpoint. |
to_date | query | string (date) | null | |
project_id | query | string (uuid)[] | |
client_id | query | string (uuid)[] | |
team_id | query | string (uuid)[] | Projects assigned to these teams. |
user_id | query | string (uuid)[] | Authors; organisation-wide views only. |
tag_id | query | string (uuid)[] | Any of these on the session, project or client. |
billing | query | "any" | "billed" | "unbilled" | Default: "any". |
scope | query | "me" | "org" | Default: "me". |
invoice_id | query | string (uuid) | null | Sessions claimed by this invoice. |
state | query | "any" | "active" | "closed" | "deleted" | Default: "any". |
origin | query | "web" | "desktop_file" | "desktop_manual" | "browser_url" | "browser_manual" | "cli_manual" | "cli_watch" | "api" | "mcp" | "mobile" | "unknown"[] | |
q | query | string | null | Case-insensitive search in descriptions. |
match | query | "overlap" | "start" | `overlap`: sessions overlapping the range; `start`: starting in it. Default: "overlap". |
changed_since | query | string (date-time) | null | Delta sync: the caller's own sessions changed after this instant, soft-deleted ones included (`deleted_at` set), oldest change first; the date range is ignored. Use `as_of` as the next value. |
- Returns
200SessionPage
POST/api/v2/sessions
Add EntryRead and write key
- Body
EntryCreate- Returns
200EntryCreateOut
POST/api/v2/sessions/start
Start TimerRead and write key
- Body
TimerStart- Returns
200TimerStartOut
GET/api/v2/sessions/active
Get ActiveRead key
- Returns
200TimerSnapshot
GET/api/v2/sessions/{session_id}
Get SessionRead key
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | string (uuid) |
- Returns
200SessionDetailOut
PATCH/api/v2/sessions/{session_id}
Update SessionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | string (uuid) |
- Body
SessionUpdate- Returns
200SessionOut
DELETE/api/v2/sessions/{session_id}
Delete SessionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | string (uuid) |
- Returns
204Successful Response
POST/api/v2/sessions/{session_id}/stop
Stop SessionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | string (uuid) |
- Body
SessionStop- Returns
200SessionOut
POST/api/v2/sessions/{session_id}/pause
Pause SessionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | string (uuid) |
- Body
PauseToggle- Returns
200PauseStateOut
POST/api/v2/sessions/{session_id}/resume
Resume SessionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | string (uuid) |
- Body
PauseToggle- Returns
200PauseStateOut
Reports
Totals per project and day in your account timezone, calculated exactly as the dashboard does.
GET/api/v2/reports/summary
Report SummaryRead key
| Name | In | Type | Description |
|---|---|---|---|
from_date | query | string (date) | null | Default depends on the endpoint. |
to_date | query | string (date) | null | |
project_id | query | string (uuid)[] | |
client_id | query | string (uuid)[] | |
team_id | query | string (uuid)[] | Projects assigned to these teams. |
user_id | query | string (uuid)[] | Authors; organisation-wide views only. |
tag_id | query | string (uuid)[] | Any of these on the session, project or client. |
billing | query | "any" | "billed" | "unbilled" | Default: "any". |
scope | query | "me" | "org" | Default: "me". |
mode | query | "sessions" | "day_span" | null | Default: the caller's full-day-span setting. |
compare | query | "none" | "previous" | `previous`: the equally long range right before (calendar unit when aligned). Default: "none". |
bucket | query | "day" | "week" | "month" | null | Default: day up to 31 days, week up to 26 weeks, else month. |
- Returns
200ReportSummaryOut
GET/api/v2/reports/time
Time ReportRead key
| Name | In | Type | Description |
|---|---|---|---|
period | query | "today" | "yesterday" | "this_week" | "last_week" | "this_month" | "last_month" | null | |
from_date | query | string (date) | null | |
to_date | query | string (date) | null | |
project_id | query | string (uuid) | null | |
group_by | query | "project" | "day" | "task"[] |
- Returns
200TimeReportOut
Clients
Billing clients of your organisation. Needs a plan with invoicing and the owner or admin role.
GET/api/v2/clients
List ClientsRead key
| Name | In | Type | Description |
|---|---|---|---|
cursor | query | string | null | |
limit | query | integer | Default: 50. |
q | query | string | null | Case-insensitive substring of name or company. |
status | query | "active" | "archived" | "all" | Default: "active". |
- Returns
200Page_ClientOut_
POST/api/v2/clients
Create ClientRead and write key
- Body
ClientCreate- Returns
200ClientOut
GET/api/v2/clients/{client_id}
Get ClientRead key
| Name | In | Type | Description |
|---|---|---|---|
client_idrequired | path | string (uuid) |
- Returns
200ClientOut
PATCH/api/v2/clients/{client_id}
Update ClientRead and write key
| Name | In | Type | Description |
|---|---|---|---|
client_idrequired | path | string (uuid) |
- Body
ClientUpdate- Returns
200ClientOut
Invoices
Invoices built from tracked work. Marking an invoice sent records it; it does not email anyone.
GET/api/v2/invoices
List InvoicesRead key
| Name | In | Type | Description |
|---|---|---|---|
cursor | query | string | null | |
limit | query | integer | Default: 50. |
status | query | "draft" | "sent" | "overdue" | "paid" | "cancelled"[] | |
client_id | query | string (uuid) | null | |
q | query | string | null | Number or client name, case-insensitive. |
- Returns
200InvoicePage
POST/api/v2/invoices
Create InvoiceRead and write key
- Body
InvoiceCreate- Returns
200InvoiceDetailOut
GET/api/v2/invoices/{invoice_id}
Get InvoiceRead key
| Name | In | Type | Description |
|---|---|---|---|
invoice_idrequired | path | string (uuid) |
- Returns
200InvoiceDetailOut
POST/api/v2/invoices/{invoice_id}/mark-sent
Mark SentRead and write key
| Name | In | Type | Description |
|---|---|---|---|
invoice_idrequired | path | string (uuid) |
- Body
MarkSent- Returns
200InvoiceDetailOut
POST/api/v2/invoices/{invoice_id}/mark-paid
Mark PaidRead and write key
| Name | In | Type | Description |
|---|---|---|---|
invoice_idrequired | path | string (uuid) |
- Body
MarkPaid- Returns
200InvoiceDetailOut
Webhooks
Subscriptions that POST signed events to your HTTPS endpoint. Delivery is at least once; deduplicate on the delivery id.
GET/api/v2/webhook-subscriptions
List Webhook SubscriptionsRead key
| Name | In | Type | Description |
|---|---|---|---|
cursor | query | string | null | |
limit | query | integer | Default: 50. |
api_key_id | query | string (uuid) | null | Cookie sessions: one key's only. |
- Returns
200Page_WebhookSubscriptionOut_
POST/api/v2/webhook-subscriptions
Create Webhook SubscriptionRead and write key
422 `unsafe_target` for non-public targets; 403 for `invoice.*` without billing role.
- Returns
200WebhookSubscriptionCreatedOut
GET/api/v2/webhook-subscriptions/{subscription_id}
Get Webhook SubscriptionRead key
| Name | In | Type | Description |
|---|---|---|---|
subscription_idrequired | path | string (uuid) |
- Returns
200WebhookSubscriptionOut
PATCH/api/v2/webhook-subscriptions/{subscription_id}
Update Webhook SubscriptionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
subscription_idrequired | path | string (uuid) |
- Returns
200WebhookSubscriptionOut
DELETE/api/v2/webhook-subscriptions/{subscription_id}
Delete Webhook SubscriptionRead and write key
| Name | In | Type | Description |
|---|---|---|---|
subscription_idrequired | path | string (uuid) |
- Returns
204Successful Response
GET/api/v2/webhook-subscriptions/{subscription_id}/deliveries
List Webhook DeliveriesRead key
| Name | In | Type | Description |
|---|---|---|---|
subscription_idrequired | path | string (uuid) | |
cursor | query | string | null | |
limit | query | integer | Default: 50. |
status | query | "pending" | "delivered" | "dead" | "cancelled" | null |
- Returns
200Page_WebhookDeliveryOut_
POST/api/v2/webhook-subscriptions/{subscription_id}/deliveries/{delivery_id}/retry
Retry Webhook DeliveryRead and write key
409 unless the delivery is dead or cancelled.
| Name | In | Type | Description |
|---|---|---|---|
subscription_idrequired | path | string (uuid) | |
delivery_idrequired | path | string (uuid) |
- Returns
200WebhookDeliveryOut
POST/api/v2/webhook-subscriptions/{subscription_id}/rotate-secret
Rotate Webhook SecretRead and write key
| Name | In | Type | Description |
|---|---|---|---|
subscription_idrequired | path | string (uuid) |
- Returns
200WebhookSecretOut
Schemas
ActiveSessionOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
user_idrequired | string (uuid) | |
organisation_idrequired | string (uuid) | |
projectrequired | ProjectRef | |
start_atrequired | string (date-time) | |
end_atrequired | string (date-time) | null | |
is_activerequired | boolean | |
is_pausedrequired | boolean | |
originrequired | "web" | "desktop_file" | "desktop_manual" | "browser_url" | "browser_manual" | "cli_manual" | "cli_watch" | "api" | "mcp" | "mobile" | "unknown" | |
is_manualrequired | boolean | |
descriptionrequired | string | |
worked_secondsrequired | integer | Pause-aware; a running session counts up to the response's `as_of`. |
tagsrequired | TagRef[] | Tags attached to the session itself. |
tasksrequired | TaskSummaryOut[] | |
files_changedrequired | integer | null | Distinct changed paths; null without file evidence. |
billingrequired | SessionBillingOut | null | |
client_session_idrequired | string (uuid) | null | Legacy idempotency key of old clients. |
device_idrequired | string (uuid) | null | |
continued_from_session_idrequired | string (uuid) | null | Set on the continuation of a live 24 h segment. |
deleted_atrequired | string (date-time) | null | Only set in change feeds (`changed_since`) and on deletion. |
versionrequired | integer | Increments on every change. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
pausesrequired | PauseOut[] | |
last_activity_atrequired | string (date-time) | null |
AddressIn
| Name | Type | Description |
|---|---|---|
line1 | string | Default: "". |
line2 | string | Default: "". |
street | string | Default: "". |
house_number | string | Default: "". |
postal_code | string | Default: "". |
city | string | Default: "". |
region | string | Default: "". |
country_code | string | null | ISO 3166-1 alpha-2. |
AddressOut
| Name | Type | Description |
|---|---|---|
line1required | string | |
line2required | string | |
streetrequired | string | |
house_numberrequired | string | |
postal_coderequired | string | |
cityrequired | string | |
regionrequired | string | |
country_coderequired | string | null | |
formattedrequired | string | One line as printed on invoices: `street no, zip city, CC`. |
BillableSplitOut
ORG-10: a resolved rate, zero included, makes time billable (DEC-19).
| Name | Type | Description |
|---|---|---|
billable_secondsrequired | integer | |
non_billable_secondsrequired | integer | |
billed_secondsrequired | integer | Claimed by an invoice. |
unbilled_secondsrequired | integer | |
by_currencyrequired | CurrencyAmountOut[] | Never summed across currencies. |
BucketOut
| Name | Type | Description |
|---|---|---|
start_daterequired | string (date) | |
end_daterequired | string (date) | |
labelrequired | string | E.g. `Mon 6`, `Week 41`, `October`. |
secondsrequired | integer | |
by_projectrequired | ProjectBucketSecondsOut[] |
ClientCreate
| Name | Type | Description |
|---|---|---|
id | string (uuid) | null | Client-generated id; a replay returns the existing client. |
namerequired | string | |
emailrequired | string | Where invoices are sent (DEC-16). |
company | string | Default: "". |
phone | string | Default: "". |
address | AddressIn | null | |
address_line | string | null | Free-text address, geocoded into fields; not with `address`. |
tax_id | string | null | |
hourly_rate | number | string | null | |
currency | string | null | Required with `hourly_rate`. |
tags | string[] |
ClientOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | |
organisation_idrequired | string (uuid) | |
namerequired | string | |
companyrequired | string | |
emailrequired | string | null | Billing email; migrated contacts may lack one (CLI-01). |
phonerequired | string | |
addressrequired | AddressOut | null | |
tax_idrequired | string | null | |
hourly_raterequired | string | null | Per hour, major units; null inherits the organisation default. |
currencyrequired | string | null | |
tagsrequired | TagRef[] | |
statusrequired | "active" | "archived" | |
archived_atrequired | string (date-time) | null | |
project_countrequired | integer | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
ClientRef
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
namerequired | string | |
companyrequired | string | |
emailrequired | string | null |
ClientSecondsOut
| Name | Type | Description |
|---|---|---|
clientrequired | NamedRef | null | Null groups projects without a client. |
secondsrequired | integer | |
sharerequired | number |
ClientUpdate
Only fields present change; null clears `address`, `tax_id`, `hourly_rate`, `currency`.
| Name | Type | Description |
|---|---|---|
name | string | null | |
email | string | null | |
company | string | null | |
phone | string | null | |
address | AddressIn | null | |
address_line | string | null | |
tax_id | string | null | |
hourly_rate | number | string | null | |
currency | string | null | |
tags | string[] | null | Full replacement. |
ComparisonOut
| Name | Type | Description |
|---|---|---|
from_daterequired | string (date) | |
to_daterequired | string (date) | |
totalsrequired | ReportTotalsOut | |
change_ratiorequired | number | null | (current - previous) ÷ previous worked time; null when previous is 0. |
ConnectedClientOut
| Name | Type | Description |
|---|---|---|
kindrequired | "web" | "desktop" | "cli" | "browser" | "mobile" | |
browserrequired | "chrome" | "edge" | "firefox" | "safari" | null | |
device_idrequired | string (uuid) | null | |
client_versionrequired | string | null | |
connected_atrequired | string (date-time) |
CredentialOut
| Name | Type | Description |
|---|---|---|
viarequired | "cookie" | "oauth" | "api_key" | |
scopesrequired | string[] | |
session_idrequired | string (uuid) | null | |
connection_idrequired | string (uuid) | null | |
api_key_idrequired | string (uuid) | null |
CurrencyAmountOut
| Name | Type | Description |
|---|---|---|
currencyrequired | string | |
billed_minorrequired | integer | From the invoice lines billing the range's sessions; cancelled ones excluded. |
unbilled_minorrequired | integer | Estimate at current rates (not an invoice). |
total_minorrequired | integer |
CurrencyTotalsOut
| Name | Type | Description |
|---|---|---|
currencyrequired | string | |
invoice_countrequired | integer | Every invoice in the selection, cancelled included. |
total_minorrequired | integer | Drafts, outstanding and paid; cancelled ones add nothing. |
draft_minorrequired | integer | |
outstanding_minorrequired | integer | Sent and overdue. |
paid_minorrequired | integer |
DaySecondsOut
| Name | Type | Description |
|---|---|---|
daterequired | string (date) | |
secondsrequired | integer |
EntitlementsOut
What the user may do right now. The one source for plan gates in every client.
| Name | Type | Description |
|---|---|---|
planrequired | "solo" | "pro" | "team" | |
sourcerequired | "subscription" | "grant" | "inherited" | "none" | |
featuresrequired | "invoicing" | "calendar" | "api" | "mcp" | "export" | "team" | "full_history"[] | |
seatsrequired | integer | Team seats the user owns as an organisation owner; else 0. |
expires_atrequired | string (date-time) | null | End of the deciding source (grant expiry or paid-through date). |
history_floorrequired | string (date-time) | null | Earliest visible instant; null means full history. |
inherited_from_organisation_idrequired | string (uuid) | null | Set when Team access comes from the org owner. |
EntryCreate
A completed time entry (TIM-04); manual entries span at most 24 h.
| Name | Type | Description |
|---|---|---|
id | string (uuid) | null | Client-generated id; a replay returns the existing entry. |
project_idrequired | string (uuid) | |
start_atrequired | string (date-time) | |
end_at | string (date-time) | null | |
duration_seconds | integer | null | Alternative to `end_at`. |
description | string | Default: "". |
tags | string[] | |
origin | "web" | "desktop_file" | "desktop_manual" | "browser_url" | "browser_manual" | "cli_manual" | "cli_watch" | "api" | "mcp" | "mobile" | Default: "web". |
is_manual | boolean | False for automatic records uploaded after the fact. Default: true. |
device_id | string (uuid) | null | |
client_session_id | string (uuid) | null | Legacy idempotency key (old clients). |
EntryCreateOut
| Name | Type | Description |
|---|---|---|
sessionrequired | SessionOut | |
createdrequired | boolean | False on an idempotent replay. |
overlappingrequired | SessionOut[] | The caller's sessions on the same project that overlap it. |
IntervalOut
| Name | Type | Description |
|---|---|---|
start_atrequired | string (date-time) | |
end_atrequired | string (date-time) |
InvoiceCreate
| Name | Type | Description |
|---|---|---|
client_idrequired | string (uuid) | |
period_start | string (date) | null | With `period_end`; both absent: all unbilled work. |
period_end | string (date) | null | |
project_ids | string (uuid)[] | |
session_ids | string (uuid)[] | |
scope | "me" | "org" | `org`: deliberately include members' work. Default: "me". |
mode | "sessions" | "day_span" | null | Default: the creator's full-day-span setting. |
overlap_strategy | "add" | "merge" | Default: "add". |
rate_overrides | RateOverride[] | |
tax_bp | integer | null | Default: the organisation's remembered rate. |
notes | string | Default: "". |
show_tasks | boolean | Default: true. |
id | string (uuid) | null | Client-generated id; a replay returns the same draft. |
InvoiceDeliveryOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
recipientrequired | string | |
subjectrequired | string | |
statusrequired | "queued" | "sent" | "failed" | |
errorrequired | string | null | |
created_atrequired | string (date-time) | |
sent_atrequired | string (date-time) | null |
InvoiceDetailOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | |
numberrequired | string | |
statusrequired | "draft" | "sent" | "overdue" | "paid" | "cancelled" | |
clientrequired | ClientRef | |
organisation_idrequired | string (uuid) | |
created_by_user_idrequired | string (uuid) | null | |
period_startrequired | string (date) | |
period_endrequired | string (date) | |
issue_daterequired | string (date) | null | |
due_daterequired | string (date) | null | |
paid_daterequired | string (date) | null | |
cancelled_atrequired | string (date-time) | null | |
timezonerequired | string | Dates and public views use this zone, never the viewer's (INV-24). |
currencyrequired | string | |
subtotal_minorrequired | integer | |
tax_bprequired | integer | |
tax_minorrequired | integer | |
total_minorrequired | integer | |
notesrequired | string | |
show_tasksrequired | boolean | |
moderequired | "sessions" | "day_span" | |
overlap_strategyrequired | "add" | "merge" | |
round_up_minutesrequired | integer | |
roundingrequired | "half_up" | "legacy_half_even" | Migrated invoices keep their old rounding. |
line_countrequired | integer | |
share_urlrequired | string | null | Public link; null after revocation. |
last_deliveryrequired | InvoiceDeliveryOut | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
linesrequired | InvoiceLineOut[] | By project name, then creation. |
deliveriesrequired | InvoiceDeliveryOut[] | Newest first. |
InvoiceLineOut
| Name | Type | Description |
|---|---|---|
projectrequired | ProjectRef | null | |
descriptionrequired | string | |
raw_secondsrequired | integer | Worked seconds of the claimed sessions before overlap and rounding. |
billable_secondsrequired | integer | |
hoursrequired | string | |
raterequired | string | null | |
rate_sourcerequired | "invoice" | "project" | "client" | "org" | "none" | "manual" | |
amount_minorrequired | integer | |
task_breakdownrequired | TaskHoursOut[] | |
session_idsrequired | string (uuid)[] | |
idrequired | string (uuid) | |
positionrequired | integer | |
kindrequired | "time" | "custom" |
InvoiceOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | |
numberrequired | string | |
statusrequired | "draft" | "sent" | "overdue" | "paid" | "cancelled" | |
clientrequired | ClientRef | |
organisation_idrequired | string (uuid) | |
created_by_user_idrequired | string (uuid) | null | |
period_startrequired | string (date) | |
period_endrequired | string (date) | |
issue_daterequired | string (date) | null | |
due_daterequired | string (date) | null | |
paid_daterequired | string (date) | null | |
cancelled_atrequired | string (date-time) | null | |
timezonerequired | string | Dates and public views use this zone, never the viewer's (INV-24). |
currencyrequired | string | |
subtotal_minorrequired | integer | |
tax_bprequired | integer | |
tax_minorrequired | integer | |
total_minorrequired | integer | |
notesrequired | string | |
show_tasksrequired | boolean | |
moderequired | "sessions" | "day_span" | |
overlap_strategyrequired | "add" | "merge" | |
round_up_minutesrequired | integer | |
roundingrequired | "half_up" | "legacy_half_even" | Migrated invoices keep their old rounding. |
line_countrequired | integer | |
share_urlrequired | string | null | Public link; null after revocation. |
last_deliveryrequired | InvoiceDeliveryOut | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
InvoicePage
| Name | Type | Description |
|---|---|---|
itemsrequired | InvoiceOut[] | |
next_cursorrequired | string | null | |
totalsrequired | CurrencyTotalsOut[] | Whole selection per currency, never converted (INV-01). |
MarkPaid
| Name | Type | Description |
|---|---|---|
paid_date | string (date) | null | Default today in the invoice timezone. |
MarkSent
| Name | Type | Description |
|---|---|---|
issue_date | string (date) | null | Default today in the invoice timezone. |
due_date | string (date) | null | Default issue date + payment terms (30 days). |
MemberRef
| Name | Type | Description |
|---|---|---|
user_idrequired | string (uuid) | |
display_namerequired | string |
MemberSecondsOut
| Name | Type | Description |
|---|---|---|
memberrequired | MemberRef | |
secondsrequired | integer | |
tracked_daysrequired | integer | |
session_countrequired | integer | |
sharerequired | number | |
projectsrequired | ProjectSecondsOut[] |
MeOrganisationOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | |
namerequired | string | |
rolerequired | "owner" | "admin" | "member" | |
statusrequired | "active" | "archived" | "closed" |
MeOut
Bootstrap for every client: one request instead of profile + settings + plan + org.
| Name | Type | Description |
|---|---|---|
userrequired | UserOut | |
settingsrequired | SettingsOut | |
organisationrequired | MeOrganisationOut | |
entitlementsrequired | EntitlementsOut | |
onboardingrequired | OnboardingOut | |
credentialrequired | CredentialOut | |
csrf_tokenrequired | string | null | Send as X-CSRF-Token on cookie-authenticated writes; null for bearer. |
NamedRef
Compact reference to a named record; also the shape of resolution candidates.
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
namerequired | string |
OnboardingOut
| Name | Type | Description |
|---|---|---|
needs_onboardingrequired | boolean | |
onboarding_seen_atrequired | string (date-time) | null | |
tour_completed_atrequired | string (date-time) | null |
Page_ClientOut_
| Name | Type | Description |
|---|---|---|
itemsrequired | ClientOut[] | |
next_cursorrequired | string | null |
Page_ProjectOut_
| Name | Type | Description |
|---|---|---|
itemsrequired | ProjectOut[] | |
next_cursorrequired | string | null |
Page_WebhookDeliveryOut_
| Name | Type | Description |
|---|---|---|
itemsrequired | WebhookDeliveryOut[] | |
next_cursorrequired | string | null |
Page_WebhookSubscriptionOut_
| Name | Type | Description |
|---|---|---|
itemsrequired | WebhookSubscriptionOut[] | |
next_cursorrequired | string | null |
PauseOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | Old integer id (old clients send it back). |
session_idrequired | string (uuid) | |
kindrequired | "manual" | "sleep" | "gap" | |
start_atrequired | string (date-time) | |
end_atrequired | string (date-time) | null | |
secondsrequired | integer | Length clipped to the session; an open pause counts up to `as_of`. |
PauseStateOut
| Name | Type | Description |
|---|---|---|
sessionrequired | SessionOut | |
pausedrequired | boolean | |
changedrequired | boolean | False when the session already was in the requested state. |
paused_sincerequired | string (date-time) | null |
PauseToggle
| Name | Type | Description |
|---|---|---|
at | string (date-time) | null | Default now; within [session start, now]. |
ProjectBillingOut
Billing fields. Present only for callers with billing authority (org owner/admin).
| Name | Type | Description |
|---|---|---|
hourly_raterequired | string | null | Project override; null inherits from client/organisation. |
currencyrequired | string | null | Currency of the project rate; null when no project rate is set. |
resolvedrequired | ResolvedRate |
ProjectBucketSecondsOut
| Name | Type | Description |
|---|---|---|
project_idrequired | string (uuid) | |
secondsrequired | integer |
ProjectCreate
| Name | Type | Description |
|---|---|---|
id | string (uuid) | null | Client-generated id; a replay returns the existing project. |
namerequired | string | |
client_id | string (uuid) | null | Billing authority; a client of the same organisation. |
hourly_rate | number | string | null | Billing authority; requires `currency`. |
currency | string | null | |
current_task | string | Default: "". |
color | string | null | |
tags | string[] |
ProjectOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | Old integer id (old CLI selects projects by it). |
organisation_idrequired | string (uuid) | |
owner_user_idrequired | string (uuid) | |
namerequired | string | |
statusrequired | "active" | "archived" | |
archived_atrequired | string (date-time) | null | |
clientrequired | NamedRef | null | |
tagsrequired | TagRef[] | |
colorrequired | string | The caller's effective colour (own choice, else the derived default). |
hiddenrequired | boolean | The caller hid the project from pickers and trackers. |
current_taskrequired | string | The caller's current task, applied to their new sessions. |
billingrequired | ProjectBillingOut | null | Owners/admins only. |
statsrequired | ProjectStatsOut | null | Only when requested (`include_stats`). |
client_project_idrequired | string (uuid) | null | Legacy idempotency key sent by the old desktop app. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
ProjectRef
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
namerequired | string | |
colorrequired | string | The caller's effective colour for the project. |
ProjectSecondsOut
| Name | Type | Description |
|---|---|---|
projectrequired | ProjectRef | |
clientrequired | NamedRef | null | |
secondsrequired | integer | |
session_countrequired | integer | |
sharerequired | number | Of the selection's total, 0 to 1. |
ProjectStatsOut
The caller's own time on the project; teammates' sessions never count (ACL-04).
| Name | Type | Description |
|---|---|---|
tracked_secondsrequired | integer | Worked seconds, running sessions counted up to the response time. |
session_countrequired | integer | |
last_activity_atrequired | string (date-time) | null |
ProjectUpdate
Only fields present change; `client_id`, `hourly_rate` and `currency` accept null.
| Name | Type | Description |
|---|---|---|
name | string | null | |
client_id | string (uuid) | null | |
hourly_rate | number | string | null | |
currency | string | null | |
tags | string[] | null | Full replacement of the project's tags. |
RateOverride
| Name | Type | Description |
|---|---|---|
project_idrequired | string (uuid) | A project in the selection. |
raterequired | number | string | |
save_to | "invoice" | "project" | "client" | "org" | Also store it as that level's default (INV-05). Default: "invoice". |
ReportSummaryOut
| Name | Type | Description |
|---|---|---|
scoperequired | "me" | "org" | |
from_daterequired | string (date) | |
to_daterequired | string (date) | |
timezonerequired | string | |
as_ofrequired | string (date-time) | |
moderequired | "sessions" | "day_span" | |
bucketrequired | "day" | "week" | "month" | |
totalsrequired | ReportTotalsOut | |
previousrequired | ComparisonOut | null | |
by_projectrequired | ProjectSecondsOut[] | Most time first, then name. |
by_clientrequired | ClientSecondsOut[] | |
by_memberrequired | MemberSecondsOut[] | null | `scope=org` only. |
by_taskrequired | TaskSecondsOut[] | |
bucketsrequired | BucketOut[] | |
timesheetrequired | TimesheetOut | |
billablerequired | BillableSplitOut | null | Billable and billed time with amounts per currency; owners/admins only. |
history_floorrequired | string (date-time) | null | Free plan: older parts of the range were clipped. |
ReportTotalsOut
| Name | Type | Description |
|---|---|---|
worked_secondsrequired | integer | Running sessions included up to `as_of`. |
active_secondsrequired | integer | The part of `worked_seconds` contributed by running sessions. |
tracked_daysrequired | integer | Local days with any session, even when fully paused. |
session_countrequired | integer | |
manual_session_countrequired | integer | |
avg_per_tracked_day_secondsrequired | integer | null | (worked - active) ÷ tracked days (WEB-14); null without tracked days. |
project_countrequired | integer | |
member_countrequired | integer |
ResolvedRate
An hourly rate after resolution: override → project → client → organisation → none.
| Name | Type | Description |
|---|---|---|
raterequired | string | null | Per hour, major units; null when nothing is configured (unpriced). |
currencyrequired | string | |
sourcerequired | "invoice" | "project" | "client" | "org" | "none" |
SessionBillingOut
The invoice claiming the session; while set, the session is locked (tags stay editable).
| Name | Type | Description |
|---|---|---|
invoice_idrequired | string (uuid) | |
invoice_numberrequired | string | |
issuedrequired | boolean | The invoice left draft: the claim can no longer be released. |
SessionDetailOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
user_idrequired | string (uuid) | |
organisation_idrequired | string (uuid) | |
projectrequired | ProjectRef | |
start_atrequired | string (date-time) | |
end_atrequired | string (date-time) | null | |
is_activerequired | boolean | |
is_pausedrequired | boolean | |
originrequired | "web" | "desktop_file" | "desktop_manual" | "browser_url" | "browser_manual" | "cli_manual" | "cli_watch" | "api" | "mcp" | "mobile" | "unknown" | |
is_manualrequired | boolean | |
descriptionrequired | string | |
worked_secondsrequired | integer | Pause-aware; a running session counts up to the response's `as_of`. |
tagsrequired | TagRef[] | Tags attached to the session itself. |
tasksrequired | TaskSummaryOut[] | |
files_changedrequired | integer | null | Distinct changed paths; null without file evidence. |
billingrequired | SessionBillingOut | null | |
client_session_idrequired | string (uuid) | null | Legacy idempotency key of old clients. |
device_idrequired | string (uuid) | null | |
continued_from_session_idrequired | string (uuid) | null | Set on the continuation of a live 24 h segment. |
deleted_atrequired | string (date-time) | null | Only set in change feeds (`changed_since`) and on deletion. |
versionrequired | integer | Increments on every change. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
working_intervalsrequired | IntervalOut[] | |
pausesrequired | PauseOut[] | |
task_segmentsrequired | TaskSegmentOut[] | |
inherited_tagsrequired | TagRef[] | Tags of the project and its client: filters match them. |
merged_from_session_idsrequired | string (uuid)[] | Sources merged into this session (provenance). |
last_activity_atrequired | string (date-time) | null | Latest file evidence. |
review_flagrequired | string | null | Migration flag such as `over_24h` or `evidence_outside_window`. |
SessionOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
user_idrequired | string (uuid) | |
organisation_idrequired | string (uuid) | |
projectrequired | ProjectRef | |
start_atrequired | string (date-time) | |
end_atrequired | string (date-time) | null | |
is_activerequired | boolean | |
is_pausedrequired | boolean | |
originrequired | "web" | "desktop_file" | "desktop_manual" | "browser_url" | "browser_manual" | "cli_manual" | "cli_watch" | "api" | "mcp" | "mobile" | "unknown" | |
is_manualrequired | boolean | |
descriptionrequired | string | |
worked_secondsrequired | integer | Pause-aware; a running session counts up to the response's `as_of`. |
tagsrequired | TagRef[] | Tags attached to the session itself. |
tasksrequired | TaskSummaryOut[] | |
files_changedrequired | integer | null | Distinct changed paths; null without file evidence. |
billingrequired | SessionBillingOut | null | |
client_session_idrequired | string (uuid) | null | Legacy idempotency key of old clients. |
device_idrequired | string (uuid) | null | |
continued_from_session_idrequired | string (uuid) | null | Set on the continuation of a live 24 h segment. |
deleted_atrequired | string (date-time) | null | Only set in change feeds (`changed_since`) and on deletion. |
versionrequired | integer | Increments on every change. |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
SessionPage
| Name | Type | Description |
|---|---|---|
itemsrequired | SessionOut[] | |
next_cursorrequired | string | null | |
as_ofrequired | string (date-time) | The instant running sessions are measured to. |
totalsrequired | SessionTotalsOut | null | Whole selection, not just this page; null in delta-sync mode. |
history_floorrequired | string (date-time) | null | Free plan: older parts of the range were clipped. |
SessionStop
| Name | Type | Description |
|---|---|---|
end_at | string (date-time) | null | Default now (clamped for stale file sessions); a set end only moves earlier. |
SessionTotalsOut
| Name | Type | Description |
|---|---|---|
session_countrequired | integer | |
active_countrequired | integer | |
worked_secondsrequired | integer |
SessionUpdate
Only fields present change; untouched instants round-trip exactly (TIM-05).
| Name | Type | Description |
|---|---|---|
project_id | string (uuid) | null | |
start_at | string (date-time) | null | |
end_at | string (date-time) | null | Setting it on a running session stops it. |
duration_seconds | integer | null | Alternative to `end_at`, from the start. |
description | string | null | This session only; no cascade. |
tags | string[] | null | Full replacement of direct tags. |
SettingsOut
| Name | Type | Description |
|---|---|---|
timezonerequired | string | null | Chosen IANA zone; null until the user (or detection) sets one. |
effective_timezonerequired | string | The zone used for day boundaries: chosen zone or server default. |
idle_timeout_secondsrequired | integer | |
sleep_resume_secondsrequired | integer | |
full_day_spanrequired | boolean | |
ai_sensitive_data_consentrequired | boolean | |
uirequired | UiPreferences |
TagRef
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
namerequired | string |
TaskHoursOut
| Name | Type | Description |
|---|---|---|
labelrequired | string | null | Null is unlabelled work ("Other work"). |
hoursrequired | string | Sums exactly to the line hours (largest remainder, INV-25). |
TaskSecondsOut
| Name | Type | Description |
|---|---|---|
namerequired | string | null | Null groups unlabelled time ("Other work"). |
secondsrequired | integer |
TaskSegmentOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
namerequired | string | |
start_atrequired | string (date-time) | |
end_atrequired | string (date-time) | null | |
secondsrequired | integer |
TaskSummaryOut
| Name | Type | Description |
|---|---|---|
namerequired | string | |
secondsrequired | integer | Pause-aware time of all segments with this name. |
activerequired | boolean | The session's open segment carries this name. |
TimeReportOut
The caller's own tracked time over a range, the running timer included.
| Name | Type | Description |
|---|---|---|
from_daterequired | string (date) | |
to_daterequired | string (date) | |
timezonerequired | string | |
as_ofrequired | string (date-time) | |
total_secondsrequired | integer | |
running_timer_includedrequired | boolean | |
by_projectrequired | ProjectSecondsOut[] | null | When grouped by project; most time first. |
by_dayrequired | DaySecondsOut[] | null | When grouped by day; days with time, ascending. |
by_taskrequired | TaskSecondsOut[] | null | When grouped by task. |
history_floorrequired | string (date-time) | null | Free plan: older parts of the range were clipped. |
TimerSnapshot
The caller's own running sessions — never widened to teammates, also not for admins.
| Name | Type | Description |
|---|---|---|
as_ofrequired | string (date-time) | |
sessionsrequired | ActiveSessionOut[] | |
clientsrequired | ConnectedClientOut[] | The caller's connected live clients (presence). |
TimerStart
| Name | Type | Description |
|---|---|---|
id | string (uuid) | null | Client-generated id; a replay returns the same session. |
project_idrequired | string (uuid) | |
start_at | string (date-time) | null | Default now; at most 5 min in the future. |
description | string | null | Default: the caller's current task. |
origin | "web" | "desktop_file" | "desktop_manual" | "browser_url" | "browser_manual" | "cli_manual" | "cli_watch" | "api" | "mcp" | "mobile" | Default: "web". |
is_manual | boolean | False for automatic starts (file activity, URL rules). Default: true. |
device_id | string (uuid) | null | |
client_session_id | string (uuid) | null | Legacy idempotency key (old clients). |
replace_others | boolean | Stop the caller's other running timers first. Default: false. |
TimerStartOut
| Name | Type | Description |
|---|---|---|
sessionrequired | SessionOut | |
createdrequired | boolean | This call created the session: the caller owns it. |
adoptedrequired | boolean | An open session already ran on the project and is returned instead. The caller did not start it and must not stop it automatically (TIM-10). |
stoppedrequired | SessionOut[] | Timers stopped because `replace_others` was set. |
TimesheetOut
| Name | Type | Description |
|---|---|---|
daysrequired | string (date)[] | |
by_projectrequired | TimesheetRowOut[] | |
by_memberrequired | TimesheetRowOut[] | null | `scope=org` only. |
TimesheetRowOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | Project id, or user id in `by_member`. |
labelrequired | string | |
seconds_by_dayrequired | integer[] | Aligned with `TimesheetOut.days`. |
total_secondsrequired | integer |
UiPreferences
Client display preferences, synced across devices; servers never act on them.
| Name | Type | Description |
|---|---|---|
theme | "system" | "light" | "dark" | Default: "system". |
mobile_shortcuts | "today" | "calendar" | "sessions" | "projects" | "clients" | "invoices" | "reports" | "team" | "settings" | "support"[] | Ordered phone tab-bar shortcuts. |
sidebar_collapsed | boolean | Default: false. |
calendar_view | "day" | "week" | "month" | Default: "week". |
UserOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
legacy_idrequired | integer | null | Old integer id; installed clients key local data by it. |
emailrequired | string | |
pending_emailrequired | string | null | New address waiting for its confirmation link to be opened. |
first_namerequired | string | |
last_namerequired | string | |
display_namerequired | string | |
email_verifiedrequired | boolean | |
has_deliverable_emailrequired | boolean | False for social sign-ups with a placeholder address. |
has_passwordrequired | boolean | |
is_staffrequired | boolean | |
created_atrequired | string (date-time) | |
deletion_scheduled_atrequired | string (date-time) | null | Set while a requested deletion is in its grace period. |
WebhookDeliveryOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
event_idrequired | string (uuid) | The business event; shared by all its deliveries. |
eventrequired | "project.created" | "session.created" | "session.closed" | "invoice.created" | "invoice.paid" | |
statusrequired | "pending" | "delivered" | "dead" | "cancelled" | |
attemptsrequired | integer | |
next_attempt_atrequired | string (date-time) | null | |
last_status_coderequired | integer | null | |
last_errorrequired | string | null | |
created_atrequired | string (date-time) | |
delivered_atrequired | string (date-time) | null |
WebhookSecretOut
| Name | Type | Description |
|---|---|---|
secretrequired | string |
WebhookSubscriptionCreate
| Name | Type | Description |
|---|---|---|
id | string (uuid) | null | |
eventrequired | "project.created" | "session.created" | "session.closed" | "invoice.created" | "invoice.paid" | |
target_urlrequired | string | |
api_key_id | string (uuid) | null | Required with a cookie session; API-key callers subscribe their own key. |
WebhookSubscriptionCreatedOut
| Name | Type | Description |
|---|---|---|
subscriptionrequired | WebhookSubscriptionOut | |
secretrequired | string | HMAC-SHA256 key for `X-Temporalist-Signature`. Returned by a create and its replays (so a retried subscribe still learns it), never by reads; rotate to replace it. |
WebhookSubscriptionOut
| Name | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
api_key_idrequired | string (uuid) | |
eventrequired | "project.created" | "session.created" | "session.closed" | "invoice.created" | "invoice.paid" | |
target_urlrequired | string | |
statusrequired | "active" | "disabled" | |
failure_countrequired | integer | Consecutive failed deliveries; reset by a success. |
last_delivery_atrequired | string (date-time) | null | |
last_status_coderequired | integer | null | |
last_errorrequired | string | null | |
created_atrequired | string (date-time) |
WebhookSubscriptionUpdate
| Name | Type | Description |
|---|---|---|
statusrequired | "active" | "disabled" |
OpenAPI
The complete machine-readable description of the API, for code generators and API tools such as Postman or Insomnia.
https://temporal.ist/api/v2/openapi.json