Time Entries API
Create a Time Entry
POST /v1/time-entries
Creates a new time entry. For agent integrations, set source to "agent" and include metadata with agent context.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
project_id | string | Yes | Project ID |
task_id | string | No | Task ID within the project |
spent_date | string | Yes | Date of work (YYYY-MM-DD) |
hours | number | Yes* | Duration in decimal hours |
is_running | boolean | No | Start a running timer (default false) |
notes | string | No | Description of work |
is_billable | boolean | No | Billable status (default from project) |
source | string | No | web, cli, api, agent (default api) |
metadata | object | No | Agent context JSON (max 4KB) |
*If is_running is true, hours defaults to 0 and increments automatically.
Example Request
curl -X POST https://api.keito.ai/v1/time-entries \
-H "Authorization: Bearer keito_sk_abc123" \
-H "Content-Type: application/json" \
-d '{
"project_id": "prj_abc",
"task_id": "tsk_001",
"spent_date": "2026-03-06",
"hours": 1.5,
"notes": "Refactored authentication module",
"source": "agent",
"metadata": {
"agent_id": "review-bot-01",
"agent_type": "claude-code",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"model": "claude-opus-4-6"
}
}'
Example Response
{
"id": "te_abc123",
"project_id": "prj_abc",
"task_id": "tsk_001",
"user_id": "usr_agent_01",
"spent_date": "2026-03-06",
"hours": 1.5,
"notes": "Refactored authentication module",
"is_running": false,
"is_billable": true,
"source": "agent",
"metadata": {
"agent_id": "review-bot-01",
"agent_type": "claude-code",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"model": "claude-opus-4-6"
},
"created_at": "2026-03-06T14:30:00Z",
"updated_at": "2026-03-06T14:30:00Z"
}
List Time Entries
GET /v1/time-entries
Returns a paginated list of time entries. Supports filtering by source, project, user, and date range.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
source | string | Filter by source |
project_id | string | Filter by project |
user_id | string | Filter by user |
from | string | Start date (inclusive) |
to | string | End date (inclusive) |
is_running | boolean | Filter running timers |
cursor | string | Pagination cursor |
limit | number | Results per page (default 50, max 200) |
Example: List Agent Entries for a Project
curl "https://api.keito.ai/v1/time-entries?source=agent&project_id=prj_abc&from=2026-03-01&to=2026-03-06" \
-H "Authorization: Bearer keito_sk_abc123"
Example Response
{
"data": [
{
"id": "te_abc123",
"project_id": "prj_abc",
"hours": 1.5,
"source": "agent",
"metadata": { "agent_id": "review-bot-01" },
"spent_date": "2026-03-06"
}
],
"next_cursor": null,
"has_more": false
}
Get a Time Entry
GET /v1/time-entries/:id
Returns a single time entry by ID.
Update a Time Entry
PATCH /v1/time-entries/:id
Updates a time entry. Commonly used to stop a running timer:
curl -X PATCH https://api.keito.ai/v1/time-entries/te_abc123 \
-H "Authorization: Bearer keito_sk_abc123" \
-H "Content-Type: application/json" \
-d '{
"hours": 1.5,
"is_running": false,
"notes": "Completed OAuth implementation"
}'
Updatable Fields
| Field | Type | Description |
|---|---|---|
hours | number | Updated duration |
notes | string | Updated description |
is_running | boolean | Stop a running timer |
is_billable | boolean | Change billable status |
task_id | string | Move to a different task |
metadata | object | Update agent context |
Note: source and project_id cannot be changed after creation.
Delete a Time Entry
DELETE /v1/time-entries/:id
Permanently deletes a time entry. Use for discarding failed agent sessions.
curl -X DELETE https://api.keito.ai/v1/time-entries/te_abc123 \
-H "Authorization: Bearer keito_sk_abc123"
Returns HTTP 204 No Content on success.