Custom Fields

Manage custom fields for contacts. Custom fields let you define org-specific attributes beyond the built-in contact properties.

All endpoints require authentication via the X-API-Key header. See Authentication.


List categories

GET /contacts/custom-fields/categories

List custom field category names used in your org.

Example request

curl https://<host>/api/contacts/custom-fields/categories \
  -H "X-API-Key: your-api-key"

Response

{
  "error": false,
  "success": true,
  "message": "Success",
  "code": 200,
  "data": ["Personal", "Academic", "Athletic"]
}

Create a custom field

POST /contacts/custom-fields

Uses a transaction to atomically create the field and increment the org's field count.

Limit: Maximum 50 custom fields per org.

Request body

FieldTypeRequiredNotes
labelstringYesDisplay name. Must be unique within the org.
typestringYesField type (e.g. text, number, boolean, date, select). Immutable after creation.
categorystringNoOptional grouping category.
valuesstring[]Noselect and multi-select only: the option labels, in display order, created with the field in the same request. Ignored for other types.

Example request

curl -X POST https://<host>/api/contacts/custom-fields \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "label": "GPA", "type": "number", "category": "Academic" }'

Response

{
  "error": false,
  "success": true,
  "message": "Custom field saved successfully",
  "code": 200,
  "data": {
    "_id": "665a...",
    "orgId": "...",
    "label": "GPA",
    "type": "number",
    "category": "Academic",
    "createdAt": 1716000000000
  }
}

Errors

StatusMessageCause
400Custom field limit reached (max 50). Have N, requested M.Org already has 50 custom fields.
400Validation errorMissing or invalid label or type.
400Custom field with label ... already existsDuplicate label within the org.

List custom fields

GET /contacts/custom-fields

Returns all custom fields for your org, sorted alphabetically by label.

Example request

curl https://<host>/api/contacts/custom-fields \
  -H "X-API-Key: your-api-key"

Response

{
  "success": true,
  "data": [
    {
      "_id": "665a...",
      "orgId": "...",
      "label": "GPA",
      "type": "number",
      "category": "Academic",
      "createdAt": 1716000000000
    }
  ]
}

Update a custom field

PUT /contacts/custom-fields/:id

Updates a custom field's label or category. The field type cannot be changed after creation.

Path parameters

ParameterTypeDescription
idstringCustom field ID.

Request body

FieldTypeRequiredNotes
labelstringNoNew display name.
categorystringNoGrouping category, or null to clear it.

Example request

curl -X PUT https://<host>/api/contacts/custom-fields/665a... \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "label": "Grade Point Average" }'

Response

{
  "error": false,
  "success": true,
  "message": "Custom field saved successfully!",
  "code": 200,
  "data": {
    "_id": "665a...",
    "label": "Grade Point Average",
    "type": "number",
    "updatedAt": 1716000100000
  }
}

Errors

StatusMessageCause
404Custom field not foundNo field with that ID in your org.
400Custom field with label ... already existsAnother field of the org already has that label.

Delete a custom field

DELETE /contacts/custom-fields/:id

Deletes a custom field. Also removes the field's values from all contacts and boards in a transaction.

Path parameters

ParameterTypeDescription
idstringCustom field ID.

Example request

curl -X DELETE https://<host>/api/contacts/custom-fields/665a... \
  -H "X-API-Key: your-api-key"

Response

{
  "success": true,
  "message": "Custom field deleted successfully!"
}

Errors

StatusMessageCause
400Field does not existNo field with that ID in your org.
400Field Id missing from paramsMissing or invalid ID parameter.

Add field values

POST /contacts/custom-fields/:id/values

Add values to a custom field (for select-type fields).

Path parameters

ParameterTypeDescription
idstringCustom field ID.

Request body

FieldTypeRequiredNotes
valuesstring[]YesValues to add.

Example request

curl -X POST https://<host>/api/contacts/custom-fields/665a.../values \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "values": ["Freshman", "Sophomore", "Junior", "Senior"] }'

Response

Standard success envelope with the updated field in data.


Update a field value

PUT /contacts/custom-fields/:id/values/:valueId

Path parameters

ParameterTypeDescription
idstringCustom field ID.
valueIdstringValue ID to update.

Example request

curl -X PUT https://<host>/api/contacts/custom-fields/665a.../values/666b... \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "value": "First Year" }'

Response

Standard success envelope with the updated field in data.


Delete a field value

DELETE /contacts/custom-fields/:id/values/:valueId

Path parameters

ParameterTypeDescription
idstringCustom field ID.
valueIdstringValue ID to delete.

Example request

curl -X DELETE https://<host>/api/contacts/custom-fields/665a.../values/666b... \
  -H "X-API-Key: your-api-key"

Response

Standard success envelope confirming deletion.


Response envelope

All endpoints use the standard envelope:

{
  "error": false,
  "success": true,
  "message": "...",
  "code": 200,
  "data": "..."
}

Error responses:

{
  "error": true,
  "success": false,
  "message": "...",
  "code": 400,
  "data": null
}

data is null for a general failure, such as a database error or an upstream timeout. When the request is rejected because of a specific field, data carries the field(s) at fault instead:

{
  "error": true,
  "success": false,
  "message": "phone: Phone parse failed: The string supplied did not seem to be a phone number (input: <masked>)",
  "code": 400,
  "data": {
    "issues": [
      {
        "path": "phone",
        "message": "Phone parse failed: The string supplied did not seem to be a phone number (input: <masked>)"
      }
    ]
  }
}

Each issue carries a path (the dotted path into the request body) and a message. A label is added when the path is not self-describing, which today means custom fields only, for example "path": "fields.68b0a1f39c2e4d0012ab77e5", "label": "Class Year". issues is an array, but treat it as holding at most one entry: validation stops at the first failure.

On this page