# Custom fields in the API and AI tools

**Category:** [Time Tracking](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/categories/time-tracking)
**Updated:** 2026-08-06

## One vocabulary everywhere

The web Reports page, the REST API and the AI agent tools all use the same spelling:

- filter with `cf_<key>`

- sort with `sort=cf:<key>`

- group with `group_by=cf:<key>`

## Discover the fields

`GET /api/v1/timetracking/custom-fields` returns every field with its key, type, picklist options, and the literal `filter_key` and `sort_key` strings, so those never have to be guessed. It also says whether each field can group a report.

Which fields apply to a given piece of time depends on the project, so `GET /api/v1/timetracking/projects` returns a `custom_fields` array per project, plus a `no_project` entry for time logged without one.

## Send values

Pass a `custom_fields` object when creating or updating an entry:

```
POST /api/v1/timetracking/entries
{
  "duration_minutes": 90,
  "project_id": "…",
  "description": "Homepage build",
  "custom_fields": { "work_type": "Build", "tags": ["a", "b"] }
}
```

Multi-select fields take an array; everything else takes a string (booleans are `"true"` / `"false"`). Sending `""` clears a field.

A missing required field returns **422** with `missing_custom_fields` naming the keys still owed. A `PATCH` that omits `custom_fields` leaves them untouched; one that includes it merges the keys given over what is stored, then validates the whole entry.

## Stopping a timer

`POST /api/v1/timetracking/timer/stop` accepts `custom_fields` and **always returns 200**. Anything still required comes back in `missing_custom_fields` to prompt for and PATCH; an invalid picklist value is dropped while the valid ones are kept.

## Filter, sort and report

`GET /api/v1/timetracking/entries?cf_work_type=Build&sort=cf:work_type&dir=asc` filters and sorts. `GET /api/v1/timetracking/report?group_by=cf:work_type` returns totals plus one row per value — use it instead of listing entries and adding them up.

Both default to your own time; add `scope=all` for the whole workspace, which requires the Time Tracking admin role. Unknown `cf_` keys and unknown sort keys are ignored rather than erroring, so a client built against an older field set keeps working.

## AI agent tools

The same capability is available to AI agents and assistants through MCP: `timetracking_list_custom_fields`, `timetracking_report`, and `custom_fields` on `timetracking_log_time` / `timetracking_list_entries`. Ask in plain language — “how many hours went to Discovery for Acme last month?” — and the agent can answer it.

---

## Related Articles

- [Track your time](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/articles/track-your-time)
- [Create a custom field](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/articles/timetracking-create-custom-field-1)
- [Templates, and giving one to a project](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/articles/timetracking-field-templates)
- [Filter, sort and group reports by a custom field](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/articles/timetracking-reporting-custom-fields-1)
- [Configure project billing and budgets](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/articles/project-billing-and-budgets)

---
[← Back to TotalCtrl Help Center](https://help.totalctrl.app/hc/totalctrl/totalctrl-help-center/en-US/)