Node SDK: Time Entries
Create a Time Entry
const entry = await keito.timeEntries.create({
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: crypto.randomUUID(),
model: 'claude-opus-4-6',
},
});
Start a Running Timer
const timer = await keito.timeEntries.startTimer({
project_id: 'prj_abc',
task_id: 'tsk_001',
spent_date: new Date().toISOString().split('T')[0],
source: 'agent',
replace_running: true,
metadata: {
agent_id: 'review-bot-01',
session_id: crypto.randomUUID(),
},
});
Omit started_time for a current, exact server-side start. started_time and ended_time are HH:mm workspace-time strings, not ISO timestamps. If another timer is already running, the API returns 409 Conflict unless you pass replace_running: true.
Stop a Timer
await keito.timeEntries.stopTimer(timer.id, {
notes: 'Completed code review',
});
The API calculates elapsed duration server-side from the timer start state.
Restart a Timer
await keito.timeEntries.restartTimer(timer.id, {
replace_running: true,
});
List Time Entries
// All agent entries for a project this week
const entries = await keito.timeEntries.list({
source: 'agent',
project_id: 'prj_abc',
from: '2026-03-01',
to: '2026-03-06',
});
for (const entry of entries.data) {
console.log(`${entry.spent_date}: ${entry.hours}h — ${entry.notes}`);
}
Pagination
let page = await keito.timeEntries.list({
project_id: 'prj_abc',
page: 1,
per_page: 50,
});
while (true) {
for (const entry of page.data) {
console.log(entry.id);
}
if (!page.hasNextPage()) break;
page = await page.nextPage();
}
Delete a Time Entry
await keito.timeEntries.delete('te_abc123');