Timesheet Approvals API

These endpoints run the same approval workflow as Time → Approval in Keito, including its preflight review, notifications, and audit log. They require the Timesheet approvals feature (Pro or Business) to be switched on for the workspace. Detect support through time-approvals-v1 in X-Keito-Features.

Each time entry’s current state is in its approval_status field. See Approval Status.

Method Endpoint Description
POST /api/v2/approvals/submit Submit your own time for approval
POST /api/v2/approvals/approve Approve a person’s submitted time and expenses
POST /api/v2/approvals/reject Reject a person’s submitted time and expenses

Dates are YYYY-MM-DD and inclusive, and a period can cover at most 366 days. Bodies are strict JSON: unknown fields return 400. Every endpoint accepts Idempotency-Key; a 409 response releases the key so you can retry with corrected input.

Permissions

Identity Submit Approve and reject
Owner or Administrator Own time Anyone in the workspace
Manager Own time Teammates assigned to them, and time on projects they manage only with the approve time on projects they manage permission
Member or contractor Own time No
Personal read-only sync key No No

A person outside your approval reach returns 403. A person or project from another workspace returns 404. If approvals are not available on the plan or are switched off, the endpoints return 403.

Submit Time

POST /api/v2/approvals/submit

Submits the authenticated person’s completed, unsubmitted, and unbilled time in the period, like Submit for approval on the Day and Week views, and notifies their approvers. There is no user_id: you cannot submit on behalf of a teammate.

Field Type Required Description
from string Yes Start date
to string Yes End date
fingerprint string No Fingerprint from an earlier submit response. If the period has changed since, the request fails with submission_stale.
curl -X POST https://app.keito.ai/api/v2/approvals/submit \
  -H "Authorization: Bearer $KEITO_API_KEY" \
  -H "Keito-Account-Id: $KEITO_ACCOUNT_ID" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: submit-2026-09-21" \
  --data '{"from":"2026-09-21","to":"2026-09-27"}'

A successful response returns submitted_count, submitted_seconds, and fingerprint. A running timer in the period returns 409 with error: "running_timer".

Approve Time

POST /api/v2/approvals/approve

Approves every submitted time entry and expense for one person in the period, optionally for one project. Approved time is locked, and its week refuses new or changed time (approved_timesheet_week_locked) until an approver withdraws the approval in Keito.

Field Type Required Description
user_id string Yes Person whose time to approve
from string Yes Start date
to string Yes End date
project_id string No Limit approval to one project
preflight_fingerprint string No Fingerprint from the preflight you reviewed
acknowledged_warning_codes string[] No Every warning code from that preflight
curl -X POST https://app.keito.ai/api/v2/approvals/approve \
  -H "Authorization: Bearer $KEITO_API_KEY" \
  -H "Keito-Account-Id: $KEITO_ACCOUNT_ID" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: approve-2026-09-21-user" \
  --data '{"user_id":"user_id","from":"2026-09-21","to":"2026-09-27"}'

A successful response returns time_entry_count, expense_count, preflight_fingerprint, and acknowledged_warning_codes. If nothing was submitted in the period, the counts are 0.

Preflight Review

Approval runs the same preflight review as the app, and the API never skips it:

409 error Meaning What to do
approval_blocked Something prevents approval, such as a running timer or unsubmitted time in the period Resolve the blocker. Blockers cannot be acknowledged.
approval_warnings_unacknowledged The review found warnings, such as hours below expected, time outside working capacity, or overlapping entries Check the returned preflight, then retry with its fingerprint as preflight_fingerprint and every warning code in acknowledged_warning_codes
approval_preflight_stale The time changed after you reviewed it Review the fresh preflight in the response and retry
approval_conflict Time changed while the approval was being saved Retry the request

Each preflight error includes the current preflight with its fingerprint, blockers, and warnings.

Reject Time

POST /api/v2/approvals/reject

Rejects a person’s submitted time and expenses in the period and returns them to the person to correct and resubmit. The reason is included in their notification and the audit log.

Field Type Required Description
user_id string Yes Person whose time to reject
from string Yes Start date
to string Yes End date
project_id string No Limit to one project
reason string No Explanation for the person, up to 2000 characters
curl -X POST https://app.keito.ai/api/v2/approvals/reject \
  -H "Authorization: Bearer $KEITO_API_KEY" \
  -H "Keito-Account-Id: $KEITO_ACCOUNT_ID" \
  -H "Content-Type: application/json" \
  --data '{"user_id":"user_id","from":"2026-09-21","to":"2026-09-27","reason":"Please split the Tuesday entry by task."}'

A successful response returns time_entry_count and expense_count.

Withdrawing an approval is available in Keito but not yet through the API.