Time Tracking Workflows
Before running these commands:
- Complete Installation
- Authenticate with Authentication
Worktimes
Important: worktimes list, worktimes read, worktimes browse, and worktimes report return only worktime rows.
They do not include absences. Use absence browse or calendar detailed when schedule context matters.
Duration display on read commands can be changed with global --duration-format:
- supported formats:
minutes(default),hours,days,hhmm daysuses fixed conversion1 day = 24h = 1440 minutes- for AI schedule analysis, prefer
calendar detailed --format json --duration-format <format>
Collect worktimes for a day:
otta worktimes list --date 2026-02-20 --format json
Read one worktime row by id:
otta worktimes read --id <worktime-id> --format json
Browse worktimes across a date range:
otta worktimes browse --from 2026-02-20 --to 2026-02-26 --format json
Generate a report for a date range as JSON:
otta worktimes report --from 2026-02-01 --to 2026-02-28 --format json
Generate a report for a date range as CSV:
otta worktimes report --from 2026-02-01 --to 2026-02-28 --format csv
List selectable IDs before add:
otta worktimes options --date 2026-02-20 --format json
Filter options when IDs are dependent:
otta worktimes options \
--date 2026-02-20 \
--project <project-id> \
--worktype <worktype-id> \
--task <task-id> \
--format json
Add a worktime (required: --project, --worktype, plus resolved user):
otta worktimes add \
--date 2026-02-20 \
--start 09:00 \
--end 17:00 \
--pause 30 \
--project <project-id> \
--user <user-id> \
--worktype <worktype-id> \
--task <task-id> \
--subtask <subtask-id> \
--superior <superior-id> \
--description "Example task description"
If --user is omitted in worktimes add, fallback order is:
OTTA_CLI_USER_ID- cached user profile (
~/.otta-cli/cache.jsonby default)
Update a worktime:
otta worktimes update \
--id <worktime-id> \
--start 10:00 \
--end 18:00 \
--description "Shifted by one hour"
Delete a worktime:
otta worktimes delete --id <worktime-id>
Minimal CRUD smoke flow (same date used in live E2E validation):
DATE=2026-02-20
MARKER="smoke-$(date +%s)"
# 1) Fetch IDs
otta worktimes options --date "$DATE" --format json
# 2) Create one row (fill IDs from options output)
otta worktimes add --date "$DATE" --start 06:00 --end 06:30 --pause 0 \
--project <project-id> --worktype <worktype-id> --description "$MARKER" --format json
# 3) Update then delete (replace <worktime-id>)
otta worktimes read --id <worktime-id> --format json
otta worktimes update --id <worktime-id> --description "${MARKER}-updated" --format json
otta worktimes delete --id <worktime-id> --format json
Holidays
Fetch holidays/workday calendar range:
otta holidays --from 2026-02-20 --to 2026-02-20 --worktimegroup <worktimegroup-id> --format json
Equivalent explicit read command:
otta holidays read --from 2026-02-20 --to 2026-02-20 --worktimegroup <worktimegroup-id> --format json
If --worktimegroup is omitted, CLI uses fallback values (if available).
Fallback order for --worktimegroup:
OTTA_CLI_WORKTIMEGROUP_ID- cached user profile (
~/.otta-cli/cache.jsonby default)
Saldo
Fetch current cumulative saldo:
otta saldo --format json
Optional explicit user id:
otta saldo --user <user-id> --format json
If --user is omitted in saldo, fallback order is:
OTTA_CLI_USER_ID- cached user profile (
~/.otta-cli/cache.jsonby default)
saldo also supports --duration-format for converted saldo output.
Absences
Browse absences across a date range (calendar-compatible split rows):
otta absence browse --from 2026-02-01 --to 2026-02-28 --format json
List selectable values for absence creation:
otta absence options --mode days --format json
otta absence options --mode hours --format json
Optional legacy raw API filter:
otta absence options --type days --format json
Add a day-based absence row (required: --type, plus resolved user):
otta absence add \
--mode days \
--type <absence-type-id> \
--from 2026-02-20 \
--to 2026-02-20 \
--description "sick leave" \
--format json
Add an hour-based absence row:
otta absence add \
--mode hours \
--type <absence-type-id> \
--from 2026-02-20 \
--start 09:00 \
--end 11:30 \
--hours 2.5 \
--description "extra hours" \
--format json
Mode notes:
--mode auto|days|hoursis supported onabsence add(autodefault).autoresolves tohoursif--start,--end, or--hoursis provided; otherwise it resolves todays.- hour mode requires
--startand--end;--tomust equal--from. absence options --mode ...needs resolved user id (--user,OTTA_CLI_USER_ID, or cached user fromotta status).- mode-specific
--typevalidation is enforced against Otta option queries:- days:
type=both||days||(empty) - hours:
type=both||hours||(empty)
- days:
If --user is omitted in absence add, fallback order is:
OTTA_CLI_USER_ID- cached user profile (
~/.otta-cli/cache.jsonby default)
Read one absence row by id:
otta absence read --id <absence-id> --format json
Update an absence row:
otta absence update --id <absence-id> --description "sick leave" --format json
Delete an absence row:
otta absence delete --id <absence-id> --format json
Minimal absence CRUD smoke flow (date used in live validation):
DATE=2026-02-20
# 1) Resolve type id
otta absence options --mode days --format json
# 2) Create one row (fill <absence-type-id>)
otta absence add --mode days --type <absence-type-id> --from "$DATE" --to "$DATE" --description "tmp-smoke" --format json
# 3) Read/update/delete (replace <absence-id>)
otta absence read --id <absence-id> --format json
otta absence update --id <absence-id> --description "sick leave" --format json
otta absence delete --id <absence-id> --format json
Generate unified calendar overview (worktimes + absences + holidays):
otta calendar overview --from 2026-02-01 --to 2026-02-28 --format json
calendar overview returns one items[] row per day in range, including weekends and days without entries.
Generate detailed calendar view (day-by-day with events, day-off reasons, and celebrations):
otta calendar detailed --from 2026-02-01 --to 2026-02-28 --format json
For AI/automation schedule checks, prefer calendar detailed --format json first.
If --worktimegroup is omitted for calendar overview or calendar detailed, fallback order is:
OTTA_CLI_WORKTIMEGROUP_ID- cached user profile (
~/.otta-cli/cache.jsonby default)
Absence Comment Helper
Generate consistent comment text for absence submissions:
otta absence comment \
--type sick \
--from 2026-02-20 \
--to 2026-02-20 \
--details "Flu symptoms, no work capacity" \
--format json
Use output text directly in Otta absence submission UI/workflow.