Number Custom Field
Store numeric values on records, with optional min/max bounds and a display prefix.
A number custom field stores a numeric value on a record — quantities, scores, measurements, or any plain number. It maps to the NUMBER value of the CustomFieldType enum and is backed by a CustomField whose value is exposed as a Float. For monetary values use the Currency field; for percentages use the Percent field.
Records are Record objects in the API.
Overview
- Type enum:
NUMBER - Optional config:
min/maxbounds (Float) and a displayprefix(String, e.g.#). - Value shape: a single
Float. On a record, read it fromCustomField.number(orCustomField.value, which returns the same bare number for this type). - Bounds enforcement:
min/maxare enforced when you create a record withcreateRecord(out-of-range values throwCUSTOM_FIELD_VALUE_PARSE_ERROR). They are not enforced bysetRecordCustomField— see Notes.
Create
Use the createCustomField mutation with type: NUMBER. The field is created in the workspace named by your blue-workspace-id header — there is no projectId argument.
mutation CreateNumberField {
createCustomField(input: { name: "Priority Score", type: NUMBER }) {
id
name
type
}
}Add min, max, and a prefix to bound and decorate the field:
mutation CreateConstrainedNumberField {
createCustomField(
input: {
name: "Team Size"
type: NUMBER
min: 1
max: 100
prefix: "#"
description: "Number of people assigned to this work"
}
) {
id
name
type
min
max
prefix
description
}
}{
"data": {
"createCustomField": {
"id": "clm4n8qwx000008l0g4oxdqn7",
"name": "Team Size",
"type": "NUMBER",
"min": 1,
"max": 100,
"prefix": "#",
"description": "Number of people assigned to this work"
}
}
}CreateCustomFieldInput
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String! | Yes | Display name of the field. |
type | CustomFieldType! | Yes | Must be NUMBER. |
min | Float | No | Lower bound. Enforced by createRecord. |
max | Float | No | Upper bound. Enforced by createRecord. |
prefix | String | No | Display prefix shown before the value (e.g. #). |
description | String | No | Help text shown to users. |
The workspace is taken from the blue-workspace-id header (ID or slug); CreateCustomFieldInput has no projectId field.
Set a value
Use the setRecordCustomField mutation with the number argument. It returns Boolean! — true on success — so it has no sub-selection.
mutation SetNumberValue {
setRecordCustomField(input: { todoId: "todo_123", customFieldId: "field_123", number: 42.5 })
}{ "data": { "setRecordCustomField": true } }SetRecordCustomFieldInput
| Parameter | Type | Required | Description |
|---|---|---|---|
todoId | String! | Yes | ID of the record to update. |
customFieldId | String! | Yes | ID of the number field. |
number | Float | No | The numeric value to store. Omit (or send null) to clear it. |
Read a value
setRecordCustomField returns only a boolean, so read the stored value back through the record’s customFields connection. Record.customFields returns [CustomField!]! directly — select the value fields on the element. For a NUMBER field, both number and value resolve to the bare numeric value.
query ReadNumberValue {
recordQueries {
todos(filter: { companyIds: ["company_123"], todoIds: ["todo_123"] }) {
items {
id
title
customFields {
id
name
type
number
value
}
}
}
}
}{
"data": {
"recordQueries": {
"todos": {
"items": [
{
"id": "clm4n8qwx000008l0g4oxdqn7",
"title": "Performance Review",
"customFields": [
{
"id": "clm4n8qwx000108l0a1b2c3d4",
"name": "Priority Score",
"type": "NUMBER",
"number": 42.5,
"value": 42.5
}
]
}
]
}
}
}
}The number and value fields resolve only when the CustomField is read in a record context (via Record.customFields); they are null when the field definition is read on its own. If no value is set, both return null.
Set a value at record creation
createRecord accepts custom-field values inline through CreateRecordInputCustomField, which carries the value as a string in the value field (there is no number argument here). The string is parsed to a number, and min/max are enforced — an out-of-range or non-numeric value throws CUSTOM_FIELD_VALUE_PARSE_ERROR.
mutation CreateRecordWithNumber {
createRecord(
input: {
title: "Performance Review"
todoListId: "list_123"
customFields: [{ customFieldId: "field_123", value: "85.5" }]
}
) {
id
title
customFields {
name
type
number
}
}
}Notes
- Bounds are enforced only at record creation.
createRecordparses the inline string value and rejects anything belowmin, abovemax, or non-numeric withCUSTOM_FIELD_VALUE_PARSE_ERROR.setRecordCustomFieldwrites thenumberargument straight to storage with no bounds check — a value outsidemin/maxis accepted and stored. Enforce bounds client-side when callingsetRecordCustomField. prefixis display-only. It is returned on the field definition for clients to render; it is not part of the stored value.- Filtering by value is done through the
fieldsJSON ofTodosFilter(aCUSTOM_FIELDentry withcustomFieldType: "NUMBER"), not through per-field operators. See List records for the fullfieldsfilter shape.
query FilterByNumber {
recordQueries {
todos(
filter: {
companyIds: ["company_123"]
projectIds: ["project_123"]
fields: [
{
type: "CUSTOM_FIELD"
customFieldId: "field_123"
customFieldType: "NUMBER"
values: ["80"]
op: "GTE"
}
]
}
) {
items {
id
title
}
}
}
}Errors
| Code | When |
|---|---|
CUSTOM_FIELD_VALUE_PARSE_ERROR | A createRecord inline value is non-numeric, below min, or above max. |
CUSTOM_FIELD_NOT_FOUND | customFieldId does not match a field in the active workspace. |
FORBIDDEN | The caller lacks permission for the operation (see Permissions). |
Permissions
- Create the field:
createCustomFieldrequires theOWNERorADMINrole on the workspace. - Set a value:
setRecordCustomFieldrequires an authenticated caller with edit access to the record (any company role, or a custom project role granting edit on the field).