# Custom Fields

Add per-board fields like Number, Text, Select, Date, and Checkbox to tasks, sort by them in table view, and manage them from agents via the API.

import { Aside, Steps } from '@astrojs/starlight/components';

## Overview

Custom fields let you attach structured data to every task on a board, beyond the built-in properties like priority, size, and due date. Each board defines its own set of fields, and every task on that board gets a value slot for each one.

Five field types are supported:

| Type | Use for |
|------|---------|
| **Number** | Ratings, scores, estimates — anything you sort numerically |
| **Text** | Free-form notes that need their own column |
| **Select** | A fixed list of options |
| **Date** | A date separate from due date |
| **Checkbox** | A yes/no flag |

The flagship use case is an **ICE rating** (a Number field for Impact/Confidence/Ease scoring) used to rank a backlog. The [ICE ranking recipe](#ice-ranking-recipe) below walks through setting one up end to end.

## Creating a field

<Steps>

1. Press `<kbd>Ctrl+K</kbd>` and search for "Create custom field".
2. Enter a name for the field.
3. Pick a type: Number, Text, Select, Date, or Checkbox.
4. Press `<kbd>Enter</kbd>` to create it.

</Steps>

The field is created on the current board and is visible by default — no separate step to turn it on.

## Setting values

Open a task and the field appears as a property row in the right rail, alongside priority, size, and due date. Click it, type or pick a value, and press `<kbd>Enter</kbd>` to save.

When you create a ticket with the [AI Task Writer](/features/ai-features/#how-it-works-today), it can fill Number, Select, Text, Date, and Checkbox fields from the board's saved instructions or past tickets. For example, a score field can match a score in the title. Values that do not fit the field are skipped. This applies to Ctrl+J compose, AI chat ticket creation, and the CLI/MCP task writer.

## Table view: columns and sorting

Every custom field on a board shows up as a column in [table view](/features/table-view/):

- **Sorting:** click a custom field's column header to sort by it. Number and Date fields sort numerically/chronologically; empty values always sort to the bottom regardless of sort direction.
- **Columns picker:** open "Configure table columns" to toggle any custom field's visibility or drag it to reorder, the same as built-in columns. "Reset to default" restores the original set.

## Views

A [saved view](/features/favorites/) captures the table's current sort, so a view sorted by a custom field stays sorted every time it's opened. This is what makes an ICE ranking view sharable: save it once, and everyone who opens the view sees the backlog in ICE order.

## ICE ranking recipe

<Steps>

1. Create a Number field named `ICE` on the board (see [Creating a field](#creating-a-field) above).
2. Open each task and set its ICE score in the right rail.
3. Switch to table view, add the ICE column if it's hidden, and click the header to sort descending.
4. Save the sorted table as a view named "ICE ranking".

</Steps>

Anyone who opens the "ICE ranking" view sees the board pre-sorted by score, no re-sorting required.

## For agents & API

Custom fields are managed through the same `Bearer htk_...` REST API used elsewhere in Hypertask ([authentication](/api/rest-api/#authentication)). Task detail responses include a `customFieldValues` array for every task on a board with custom fields defined.

### Create a field

**Endpoint:** `POST /api/mcp/custom-fields`

Creating a field is idempotent on `name` — calling create again with a name that already exists on the board returns the existing field instead of erroring.

```bash
curl -s -X POST \
  -H "Authorization: Bearer $HT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"project_id": 123, "name": "ICE", "type": "number"}' \
  "https://app.hypertask.ai/api/mcp/custom-fields"
```

**Response example:**

```json
{
  "fieldId": 789,
  "name": "ICE",
  "type": "number"
}
```

### Set a value

**Endpoint:** `POST /api/mcp/custom-fields/value`

Accepts either `field_id` or `field_name`. The recommended surface is to first create the field via `POST /api/mcp/custom-fields`, obtaining `field_id`, then assign values. Values are strictly validated against the field's type — for example, a non-numeric value sent to a Number field is rejected with a `400` response.

**Set value by field_id**

```bash
curl -s -X POST \
  -H "Authorization: Bearer $HT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task_id": 789, "field_id": 789, "value": 42}' \
  "https://app.hypertask.ai/api/mcp/custom-fields/value"
```

**Switch to field_name (auto-creates the field first)**

```bash
curl -s -X POST \
  -H "Authorization: Bearer $HT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task_id": 789, "field_name": "ICE", "value": 42}' \
  "https://app.hypertask.ai/api/mcp/custom-fields/value"
```

**Tips:**

- Use `field_id` in named endpoints after retrieval for clarity.
- Typed values must match the field's declared type.
- Empty or unset values are represented as `null` unless overridden.

### Delete a field

**Endpoint:** `DELETE /api/mcp/custom-fields/{fieldId}`

```bash
curl -s -X DELETE \
  -H "Authorization: Bearer $HT_API_KEY" \
  "https://app.hypertask.ai/api/mcp/custom-fields/456"
```

Deleting a field removes every task's value for it. This can't be undone.

<Aside type="caution">
A board can have up to **50 custom fields**, and field names are capped at **64 characters**. Requests past either limit are rejected.
</Aside>
