Formula Field

Aggregate custom field values (SUM, AVERAGE, COUNT, MIN, MAX) for charts and dashboards.


A Formula field defines an aggregation — SUM, AVERAGE, COUNT, MIN, MAX — over the values of other custom fields. Formula fields power chart segments and dashboards: they roll values up across the records in a workspace rather than computing a per-record value. Records are Todo objects and workspaces are Project objects in the API.

Create a Formula field with the createCustomField mutation, passing type: FORMULA. The field is created in the workspace identified by the blue-workspace-id header.

Formulas aggregate; they don't compute per record

A Formula field has no per-record value. It produces a single aggregated number that surfaces on chart segments (ChartSegment.formulaResult), not on each Todo. Use a Rollup field if you need per-record computed values.

Create

The formula argument on createCustomField is typed JSON, so you pass the formula definition as a free-form object. Use the same shape as the typed FormulaInput (a logic block plus a display block) so the field renders identically to one configured in the app.

mutation CreateFormulaField {
  createCustomField(
    input: {
      name: "Budget Total"
      type: FORMULA
      formula: {
        logic: { text: "Budget Total", html: "<span>Budget Total</span>" }
        display: { type: NUMBER, precision: 2, function: SUM }
      }
    }
  ) {
    id
    name
    type
    formula
  }
}

CreateCustomFieldInput

ParameterTypeRequiredDescription
nameString!YesDisplay name of the field.
typeCustomFieldType!YesMust be FORMULA.
formulaJSONNoFormula definition. Use the FormulaInput shape below.
descriptionStringNoHelp text shown next to the field.

The workspace is taken from the blue-workspace-id header, not from the input. There is no projectId field on CreateCustomFieldInput.

Formula shape

createCustomField accepts formula as JSON; editCustomField accepts it as the typed FormulaInput. Both expect the same structure:

FieldTypeRequiredDescription
logicFormulaLogicInput!YesLabel for the formula.
logic.textString!YesPlain-text label.
logic.htmlString!YesHTML label used in the app UI.
displayFormulaDisplayInput!YesHow the result is computed and formatted.
display.typeFormulaDisplayType!YesNUMBER, CURRENCY, or PERCENTAGE.
display.functionChartFunctionNoAggregation function (see below).
display.precisionFloatNoNumber of decimal places.
display.currencyFormulaDisplayCurrencyInputNoCurrency code + name; only with display.type: CURRENCY.

ChartFunction

ValueAggregation
SUMSum of all values.
AVERAGEMean of all values.
AVERAGEAMean, treating empty values as zero.
COUNTCount of non-empty numeric values.
COUNTACount of all values, including empty.
MAXLargest value.
MINSmallest value.

FormulaDisplayType

ValueFormattingExample
NUMBERPlain number with optional precision.1250.75
CURRENCYFormatted with currency.code.$1,250.75
PERCENTAGENumber with a % suffix.87.5%

Response

createCustomField returns the created CustomField. The stored definition comes back on formula (typed JSON).

{
  "data": {
    "createCustomField": {
      "id": "clm4n8qwx000008l0g4oxdqn7",
      "name": "Budget Total",
      "type": "FORMULA",
      "formula": {
        "logic": { "text": "Budget Total", "html": "<span>Budget Total</span>" },
        "display": { "type": "NUMBER", "precision": 2, "function": "SUM" }
      }
    }
  }
}

Returns

FieldTypeDescription
idID!The custom field’s identifier.
nameString!Display name.
typeCustomFieldType!Always FORMULA for this field.
formulaJSONThe stored formula definition.
descriptionStringHelp text, if set.

A Formula field has no per-record value. The aggregated result is computed asynchronously and exposed on ChartSegment.formulaResult (a Float) when the field is used in a chart — it is not returned on the CustomField itself or on any record.

Full example

A currency formula that averages a numeric field, formatted in US dollars to two decimal places.

mutation CreateRevenueAverage {
  createCustomField(
    input: {
      name: "Average Deal Size"
      description: "Mean value across all deals in this workspace"
      type: FORMULA
      formula: {
        logic: { text: "Average Deal Size", html: "<span>Average Deal Size</span>" }
        display: {
          type: CURRENCY
          currency: { code: "USD", name: "US Dollar" }
          precision: 2
          function: AVERAGE
        }
      }
    }
  ) {
    id
    name
    formula
  }
}

Edit

Use editCustomField to change an existing Formula field. Here formula is the typed FormulaInput (same shape as create, but type-checked by the schema). Pass the field’s id as customFieldId.

mutation UpdateFormulaField {
  editCustomField(
    input: {
      customFieldId: "field_123"
      formula: {
        logic: { text: "Completion Rate", html: "<span>Completion Rate</span>" }
        display: { type: PERCENTAGE, precision: 1, function: AVERAGE }
      }
    }
  ) {
    id
    name
    formula
  }
}

Errors

CodeWhen
BAD_USER_INPUTThe input is invalid (for example, a malformed formula block).
CUSTOM_FIELD_NOT_FOUNDeditCustomField was given a customFieldId that doesn’t exist.
FORBIDDENThe caller isn’t an OWNER or ADMIN of the workspace.

Permissions

Creating and editing custom fields requires the OWNER or ADMIN role on the workspace. Reading a field’s aggregated result requires view access to the chart or dashboard it appears on.