Reports API

Keito exposes project-level financial reports for integrations that need to reconcile budgets and uninvoiced work without downloading raw financial records.

Both endpoints require a full-access API key bound to a user with the relevant Keito permissions. A key never grants more access than its user has:

Bound user Project budget report Uninvoiced report Project visibility
Owner or Administrator Yes Yes All workspace projects
Manager Requires View billable rates Requires View billable rates and View invoices Actively managed projects only
Other member No No None
Personal read-only sync key No No None

Keito does not currently provide a workspace-wide read-only reporting credential. Use a full-access integration key created for an appropriately permissioned user, store it as a secret, and rotate or revoke it when the integration is retired.

Project Budget Report

GET /api/v2/reports/project_budget

This is the supported equivalent of Harvest’s GET /v2/reports/project_budget.

Request

curl "https://app.keito.ai/api/v2/reports/project_budget?is_active=true&per_page=2000" \
  -H "Authorization: Bearer $KEITO_API_KEY" \
  -H "Keito-Account-Id: $KEITO_ACCOUNT_ID"
Parameter Type Required Description
is_active boolean No Return active or inactive projects only.
page integer No Page number, starting at 1.
per_page integer No Results per page, default and maximum 2000.

Response

{
  "results": [
    {
      "project_id": "clxproject123",
      "project_name": "Implementation",
      "client_id": "clxclient123",
      "client_name": "Example Client",
      "budget_is_monthly": false,
      "budget_by": "project",
      "is_active": true,
      "budget": 20000,
      "budget_spent": 5250,
      "budget_remaining": 14750
    }
  ],
  "per_page": 2000,
  "total_pages": 1,
  "total_entries": 1,
  "next_page": null,
  "previous_page": null,
  "page": 1,
  "links": {
    "first": "/api/v2/reports/project_budget?page=1&is_active=true&per_page=2000",
    "next": null,
    "previous": null,
    "last": "/api/v2/reports/project_budget?page=1&is_active=true&per_page=2000"
  }
}

budget, budget_spent, and budget_remaining use the unit selected by budget_by. For fee budgets, spend is rounded time multiplied by the historical effective project, task, or person rate for the entry’s work date. A later change to a person’s default rate does not reprice earlier work. Invoice discounts, payments, taxes, and retainer credits do not change budget consumption.

For hours budgets, the values are hours. For project-cost budgets, they are internal cost and are protected by the same elevated financial permissions.

Uninvoiced Report

GET /api/v2/reports/uninvoiced

This is the supported equivalent of Harvest’s GET /v2/reports/uninvoiced?from=...&to=....

Request

curl "https://app.keito.ai/api/v2/reports/uninvoiced?from=20260101&to=20260131&per_page=2000" \
  -H "Authorization: Bearer $KEITO_API_KEY" \
  -H "Keito-Account-Id: $KEITO_ACCOUNT_ID"
Parameter Type Required Description
from string Yes Inclusive start date in YYYYMMDD format.
to string Yes Inclusive end date in YYYYMMDD format. The range cannot exceed 365 days.
include_fixed_fee boolean No Include fixed-fee projects and their remaining fee balance. Defaults to true.
page integer No Page number, starting at 1.
per_page integer No Projects per page, default and maximum 2000.

Response

{
  "results": [
    {
      "client_id": "clxclient123",
      "client_name": "Example Client",
      "project_id": "clxproject123",
      "project_name": "Implementation",
      "currency": "GBP",
      "total_hours": 42.5,
      "uninvoiced_hours": 12.5,
      "uninvoiced_expenses": 125,
      "uninvoiced_amount": 1375
    }
  ],
  "per_page": 2000,
  "total_pages": 1,
  "total_entries": 1,
  "next_page": null,
  "previous_page": null,
  "page": 1,
  "links": {
    "first": "/api/v2/reports/uninvoiced?page=1&from=20260101&to=20260131&per_page=2000",
    "next": null,
    "previous": null,
    "last": "/api/v2/reports/uninvoiced?page=1&from=20260101&to=20260131&per_page=2000"
  }
}

Calculation Rules

  • Time and expenses are filtered by their work or spent date, inclusive of from and to.
  • Only billable, unbilled work is included. Running and rejected time is excluded.
  • If the workspace allows documented work before approval, unsubmitted, submitted, and approved time and expenses are included. Otherwise, only approved work is included.
  • Time uses the workspace rounding rule and the historical effective billing rate for the entry’s work date.
  • Expenses contribute their recorded billable cost.
  • For time-and-materials projects, uninvoiced_amount is unbilled time at those historical rates plus eligible unbilled expenses.
  • For fixed-fee projects, the service amount is the project fee minus non-voided service invoice lines. It becomes eligible when the report end date reaches the project’s start date, or its creation date when no start date exists. The from date does not split that outstanding fixed-fee balance.
  • Payments, invoice discounts, taxes, retainer funding, and retainer credits do not reduce the fixed-fee balance. Set include_fixed_fee=false to omit fixed-fee projects.

Task or Category Hours

To reproduce cumulative hours by Harvest task/category, list time entries for the same date range and group rounded_hours by task_id (or by task.name from the embedded task object):

curl "https://app.keito.ai/api/v2/time_entries?from=2026-01-01&to=2026-01-31&per_page=2000" \
  -H "Authorization: Bearer $KEITO_API_KEY" \
  -H "Keito-Account-Id: $KEITO_ACCOUNT_ID"

Time-entry responses expose rounded_hours, budgeted, is_billed, and an authorized stored historical billable_rate. They do not expose a calculated billable_amount or approval_status; use the financial report endpoints for invoice-eligible monetary totals.

Capability Detection

Responses include financial-reports-v1 in the X-Keito-Features header. Treat a 403 as a credential or bound-user permission failure, not as an empty report.