Concepts
API requests and responses use snake_case. Each resource has its own schema and permission-filtered projection; a field present in one endpoint is not guaranteed in another.
Time entries
A new time entry requires a project, an assigned task and a spent_date (YYYY-MM-DD). Completed durations use decimal hours; running timers use the dedicated timer contract.
| Field | Meaning |
|---|---|
id, project_id, task_id, user_id |
Keito record IDs; discover them rather than inventing prefixes |
spent_date |
Date the work belongs to, separate from creation time |
hours, rounded_hours |
Recorded duration and workspace-rounded duration |
billable |
Whether the entry is billable; the entry field is not is_billable |
is_running, timer_started_at |
Running state and exact timer start |
started_time, ended_time |
Optional HH:mm workspace-local times, not ISO timestamps |
approval_status, is_locked, is_billed |
Approval, edit and billing state |
invoice_id |
Nullable read-only Keito invoice link in the normal entry projection |
metadata |
Optional JSON context, at most 4 KB |
Billable rates are returned only when authorized. Do not replace omitted rates with zero or infer permissions from a source label.
Expenses
Every expense belongs to a project and category. An amount-based category accepts total_cost; a per-unit category accepts units and calculates cost from its configured rate.
| Field | Meaning |
|---|---|
project_id, expense_category_id, spent_date |
Project, category and expense date |
total_cost, currency |
Recorded amount and denomination |
units |
Optional quantity, including supported fractional units |
expense_category.unit_price |
Configured category rate; not a writable top-level expense price |
entry_type, adjustment_reason, adjustment_of_id |
Ordinary expense or typed refund adjustment |
receipt_url |
Authenticated file URL when a receipt is stored |
attach_receipt_to_invoice |
Separate choice to include that receipt on eligible future invoices |
billable, approval_status, is_billed |
Separate client-billability, approval and invoicing state |
Creating an expense does not move money. Reimbursement classification and repayment history are separate from ordinary expense creation; see Expenses API.
Users and credentials
Users API distinguishes the administrator directory, /users/me, and reduced personal-sync projections. Directory users use first_name and last_name; current-user and personal-sync responses have their own field sets. Never require email, company, capacity or financial fields on every user object.
An API key acts as its bound identity, inside the selected workspace and its current role/record permissions. A full-access key means all operations that identity is permitted to perform. It does not make a Member an Administrator. Personal sync keys have a fixed read-only allowlist.
Sources and metadata
The source records origin, not authority or a billing decision. Time-entry reads can include web, CLI, API, agent, calendar, desktop, mobile and integration-specific origins. Writable values and filters depend on the endpoint; use its schema rather than assuming every read source is accepted on create. Expenses accept web, cli, api and agent.
For ordinary custom automation, use source: "api" and nonsensitive metadata:
{
"source": "api",
"metadata": {
"session_id": "operation-unique-001",
"integration": "receipt-parser"
}
}
Keito’s source: "agent" lifecycle capture has a separate validated metadata contract. Human-owned completed lifecycle sessions require skill: "keito-time-track", session_id and positive duration_seconds; Agent identities use the controlled public-build contract. An arbitrary token-count object is not a valid replacement. Use the Agent Skill for supported automatic lifecycle capture or the explicit SDK wrapper for your own API automation.
Metadata is stored and may be shown in reports. Do not put credentials, receipt contents, prompts or other sensitive material in it. Token counts alone do not calculate an expense price.