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.

Existing keys, including keys issued before the planning endpoint was added, gain this one planning read without rotation.

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 eight requests. Planning also requires Business and your current own-schedule permission:

Method Endpoint Access
GET /api/v2/planning/me Your own schedule only; see Planning API
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.

In particular, the key cannot access /api/v2/tasks and cannot be used for Keito CLI time tracking. Keito CLI v0.1.8 and later recognises this credential and returns a clear compatibility error instead of treating the reduced /api/v2/users/me response as malformed.

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.

  1. Sign in to Keito.
  2. Open Settings -> API & Developers.
  3. Under Personal read-only sync key, select Create read-only sync key.
  4. Copy the kto_... key immediately. Keito displays the secret once.
  5. 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.

Eligible Members and Managers can also create a read-only key under Personal API keys by entering a name and selecting Read-only sync in API key access. Selecting All permitted operations instead creates a separate key for the CLI and operations allowed by your current permissions; it does not change an existing sync key.

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.

invoice_id is not included in personal sync time-entry responses, and the invoice_id filter is not supported. Invoice linkage is available through the normal Time Entries API response with a credential permitted to use it.

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.

The replacement remains read-only. Rotation never adds endpoints or write access.

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 eight read operations described here. There is no permission toggle that upgrades it. For the Keito CLI, /api/v2/tasks, or writes, eligible active internal Members and Managers can create a new key under Settings > API & Developers > Personal API keys and select All permitted operations in API key access. The new key follows that person’s current permissions and record access. Update the integration to use the new key; existing read-only keys and their rotations remain read-only.

A workspace Administrator can issue a full-access integration key for another member or an Agent identity. Agent identities cannot create personal keys themselves.

See API Keys for shared authentication guidance and Scopes & Permissions for the difference between credential types.