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.

  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.

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.