Projects API
Project API access follows the current Keito permissions and active project assignments of the user bound to the credential.
Visibility and Permissions
| Identity | Read | Create | Update, archive, restore | Delete |
|---|---|---|---|---|
| Owner or Administrator | All workspace projects | Yes | Yes | Yes |
| Manager with Edit projects | Actively assigned projects | Yes | Only assigned projects they manage | No |
| Other active internal user | Actively assigned projects | No | No | No |
| Personal read-only sync key | Assigned project list and item reads | No | No | No |
Changing a role, Manager permission, active assignment, or project-manager status takes effect on the next request. A missing, cross-workspace, or unassigned project returns 404, so callers cannot use the API to discover inaccessible records.
Rates, fees, budgets, task budgets, and internal costs are omitted unless the bound user has the corresponding financial visibility in Keito. Collection, item, and mutation responses use the same redaction.
List Projects
GET /api/v2/projects
Supported query parameters are is_active, client_id, updated_since, owner_id, page, and per_page. Personal read-only sync keys support is_active, owner_id, page, and per_page only.
curl "https://app.keito.ai/api/v2/projects?is_active=true&per_page=100" \
-H "Authorization: Bearer $KEITO_API_KEY" \
-H "Keito-Account-Id: $KEITO_ACCOUNT_ID"
Get a Project
GET /api/v2/projects/{id}
A successful item read returns an ETag for the exact permission-filtered representation. Financial-visibility changes therefore change the validator.
Create a Project
POST /api/v2/projects
client_id and name are required. You may also set owner_id, code, notes, dates, task_ids, and consistent billing and budget settings. Commercial properties require the same elevated billable-rate permission as the Keito interface.
curl -X POST "https://app.keito.ai/api/v2/projects" \
-H "Authorization: Bearer $KEITO_API_KEY" \
-H "Keito-Account-Id: $KEITO_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: project-create-001" \
--data '{"client_id":"client_id","name":"Example project","code":"EXAMPLE"}'
Omit task_ids to assign workspace default tasks, or pass an empty array to assign none. Cross-workspace or inactive relationship IDs are rejected. A successful create returns 201 Created, Location, and ETag.
Update, Archive, or Restore
PATCH /api/v2/projects/{id}
Owners and Administrators may update any visible project. A Manager needs Edit projects and must currently manage that project. Use is_active: false to archive and is_active: true to restore.
curl -X PATCH "https://app.keito.ai/api/v2/projects/$PROJECT_ID" \
-H "Authorization: Bearer $KEITO_API_KEY" \
-H "Keito-Account-Id: $KEITO_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-H 'If-Match: "etag-from-the-latest-read"' \
-H "Idempotency-Key: project-update-001" \
--data '{"name":"Updated project"}'
If-Match is optional for PATCH but strongly recommended. A stale value returns 412 Precondition Failed.
Permanently Delete a Project
DELETE /api/v2/projects/{id}
Permanent deletion is Owner/Administrator-only. The project must already be archived and the request must include the latest If-Match; missing or stale preconditions return 428 or 412. Keito removes project-bound time, expenses, assignments, tasks, and integration mappings while preserving historical invoice lines. Dependencies that cannot be preserved return 409.
Use a disposable project, archive it first, and confirm invoice-history requirements before testing deletion. Deletion cannot be undone.
Tasks and Project Task Budgets
Tasks are reusable across a workspace, while their budgets belong to a task’s assignment to a project. A workspace-global GET /api/v2/tasks omits budget. To return the active project-task assignment budget, pass project_id:
curl "https://app.keito.ai/api/v2/tasks?project_id=$PROJECT_ID&is_active=true" \
-H "Authorization: Bearer $KEITO_API_KEY" \
-H "Keito-Account-Id: $KEITO_ACCOUNT_ID"
Use project context when choosing a task for a time entry: Keito validates that the task is actively assigned to the selected project and may apply member-specific task restrictions. Personal read-only sync keys cannot call /api/v2/tasks; their fixed allowlist provides project directory reads only.
budget can be 0 or null. Keito omits it when there is no project context, the assignment is inactive or missing, or the caller cannot view that project’s budget. Nested project tasks follow the same rule. Detect support through project-task-budgets in X-Keito-Features.
Safe Retries and Request Rules
Mutation requests may include an Idempotency-Key containing 8–255 letters, numbers, dots, underscores, or hyphens. The same key, request, precondition, and authorization context replays the stored response for 24 hours. Reusing a key for different input, after a permission change, or while the original request is still running returns 409.
Bodies must be uncompressed UTF-8 application/json, are limited to 128 KiB, and use strict schemas. Unknown properties, empty updates, inconsistent billing settings, invalid date ranges, and out-of-range amounts are rejected. Responses are private, no-store.