Personal Read-Only Sync Keys
Use a personal read-only sync key when an integration needs to export a user’s own time and read the users, clients, and projects that user can see without changing Keito data.
The key is bound to the user and workspace that created it. Its endpoint allowlist is fixed, while record visibility is reevaluated from that user’s current Keito permissions on every request.
Access Provided
The key is accepted for seven requests:
| Method | Endpoint | Access |
|---|---|---|
GET |
/api/v2/time_entries |
The key owner’s time entries only |
GET |
/api/v2/users |
Minimal internal human directory for the workspace |
GET |
/api/v2/users/me |
The key owner’s profile and read capabilities |
GET |
/api/v2/clients |
Clients visible to the key owner in Keito |
GET |
/api/v2/clients/{id} |
One visible client |
GET |
/api/v2/projects |
Minimal directory of actively assigned projects |
GET |
/api/v2/projects/{id} |
One actively assigned project, with permission-based redaction |
It is not accepted for other API operations and cannot create, edit, or delete data.
The project directory includes active and archived projects only while the key owner has an active assignment. Removing that assignment removes list and item visibility on the next request. Client reads match the client list visible to that user in Keito.
The key never exposes financial or internal-cost properties that the user cannot see in Keito. Time-entry notes are included; private internal notes are not.
Create a Key
Active Members, Managers, and Contractors can create a key for themselves. Client memberships and Agent identities cannot create personal sync keys.
- Sign in to Keito.
- Open Settings -> API & Developers.
- Under Personal read-only sync key, select Create read-only sync key.
- Copy the
kto_...key immediately. Keito displays the secret once. - Copy the Company ID shown on the same page.
Each user creates their own key for each workspace they want to sync. Do not share one user’s key with another user.
Authenticate
Send the key and Company ID on every request:
curl "https://app.keito.ai/api/v2/users/me" \
-H "Authorization: Bearer $KEITO_API_KEY" \
-H "Keito-Account-Id: $KEITO_ACCOUNT_ID"
Keep the key in a server-side secret store or environment variable. Do not place it in browser code, mobile applications, URLs, source control, screenshots, support messages, or logs.
Response Contracts
Personal sync responses use smaller schemas than full-access API responses.
Current User
GET /api/v2/users/me returns only:
{
"id": "user_id",
"first_name": "Example",
"last_name": "User",
"email": "user@example.com",
"is_active": true,
"is_contractor": false,
"roles": ["member"],
"capabilities": {
"can_read_own_time_entries": true,
"can_read_users": true,
"can_read_own_profile": true,
"can_read_clients": true,
"can_read_projects": true
}
}
Identity-selection parameters such as user_id are not accepted on this endpoint.
User Directory
GET /api/v2/users returns active and inactive internal human memberships so a sync can deactivate historical users. It excludes Client memberships and Agent identities.
Each users item contains exactly:
{
"id": "user_id",
"first_name": "Example",
"last_name": "User",
"is_active": true,
"is_contractor": false,
"roles": ["member"]
}
Supported query parameters are is_active, page, and per_page. Omit is_active to include active and inactive memberships; otherwise use exactly true or false.
Project Directory
GET /api/v2/projects returns active and inactive projects to which the key owner is actively assigned.
Each projects item contains exactly:
{
"id": "project_id",
"name": "Example project",
"code": "EXAMPLE",
"is_active": true,
"owner_id": "owner_user_id",
"owner": {
"id": "owner_user_id",
"name": "Project owner",
"email": "owner@example.com"
},
"client": {
"id": "client_id",
"name": "Example client"
}
}
Supported query parameters are is_active, owner_id, page, and per_page. Omit is_active to include active and inactive assigned projects; otherwise use exactly true or false. An unassigned item ID returns 404.
Client Reads
GET /api/v2/clients and GET /api/v2/clients/{id} follow the key owner’s current client visibility. The collection supports is_active, updated_since, page, and per_page. An inaccessible or cross-workspace ID returns 404.
Own Time Entries
GET /api/v2/time_entries always limits results to the key owner. Omit user_id or pass the key owner’s ID. Another user’s ID returns 403 Forbidden, including when the key owner is a Manager.
Supported filters are:
| Parameter | Format | Description |
|---|---|---|
client_id |
ID | Match entries for a client |
user_id |
ID | Omit or use the key owner’s ID |
task_id |
ID | Match entries for a task |
task |
ID | Backwards-compatible alias for task_id |
from |
YYYY-MM-DD |
Inclusive start date |
to |
YYYY-MM-DD |
Inclusive end date |
updated_since |
ISO 8601 timestamp | Entries updated at or after the timestamp |
page |
positive integer | Page number |
per_page |
positive integer | Results per page |
If both task and task_id are present, their values must match. Invalid, blank, or conflicting filter values return 400 Bad Request.
Each time_entries item contains only:
id, user_id, project_id, task_id, spent_date, hours,
duration_seconds, rounded_hours, notes, is_running,
timer_started_at, started_time, ended_time, is_locked,
is_closed, is_billed, billable, source, created_at, updated_at
Filters narrow the key owner’s workspace-scoped results; they never expand access.
Pagination
Directory and time-entry responses use the standard API v2 pagination envelope:
{
"page": 1,
"per_page": 100,
"total_pages": 1,
"total_entries": 1,
"links": {
"first": "...",
"next": null,
"previous": null,
"last": "..."
}
}
The response also contains the endpoint-specific users, clients, projects, or time_entries array.
Rotate or Revoke
Select Rotate to replace a key. The previous key remains valid for 15 minutes so you can update the integration without interruption.
Select Revoke when a key is no longer needed or may have been exposed. Revocation is immediate, including during a rotation handover.
After rotating, update the secret in your integration and verify GET /api/v2/users/me before removing the previous value.
Choosing the Right Key
Use a personal read-only sync key for the seven read operations described here. If an integration must create or modify Keito data, an Administrator must review that need and use the appropriate full-access integration credential instead.
See API Keys for shared authentication guidance and Scopes & Permissions for the difference between credential types.