Skip to content

Custom Attributes

Define and manage custom fields on employees, contractors, vacancies, teams, and projects. Custom attributes let you extend Flowstate's data model with organization-specific fields -- cost centre codes, department tags, compliance flags, or anything else your workflows need.

Two-part model

Custom attributes have two parts: definitions (the field schema, configured once per organization) and values (the data set on individual entities). Create definitions first, then set values on entities.

Custom Attribute Definition Object

A definition describes one custom field -- its name, data type, and which entity types it applies to.

FieldTypeDescription
idstringUnique identifier (CUID format). System-generated. Read-only.
namestringDisplay name (e.g. "Cost Centre Code"). Unique within your organization.
attributeKeystringImmutable machine key for API and integration usage (e.g. "cost_centre_code"). Lowercase alphanumeric with underscores, starting with a letter. Max 100 characters. Auto-generated from name if omitted on creation.
fieldTypestringData type: STRING, NUMBER, DATE, or DATE_RANGE.
entityTypesstring[]Entity types this attribute applies to. One or more of: EMPLOYEE, TEAM, PROJECT, VACANCY, CONTRACTOR.
descriptionstring | nullOptional description of what this attribute tracks.
isRequiredbooleanWhether this attribute is required when editing an entity. Default: false.
isActivebooleanWhether this attribute is active and visible. Default: true.
sortOrderintegerDisplay sort order. Lower numbers appear first. Default: 0.
createdAtdatetime (ISO 8601)When the definition was created. Read-only.
updatedAtdatetime (ISO 8601)When the definition was last modified. Read-only.

attributeKey is immutable

The attributeKey is set once during creation and cannot be changed. If you need a different key, delete the definition and create a new one. Any attributeKey passed in a PATCH request is silently ignored.


Custom Attribute Value Object

A value stores the data for one custom attribute on one entity.

FieldTypeDescription
idstringUnique identifier (CUID format). System-generated. Read-only.
definitionIdstringID of the custom attribute definition.
entityTypestringEntity type (EMPLOYEE, TEAM, PROJECT, VACANCY, or CONTRACTOR).
entityIdstringID of the entity this value belongs to.
stringValuestring | nullValue for STRING field type. Max 255 characters.
numberValuenumber | nullValue for NUMBER field type.
dateValuedatetime (ISO 8601) | nullValue for DATE field type.
dateRangeStartdatetime (ISO 8601) | nullStart date for DATE_RANGE field type.
dateRangeEnddatetime (ISO 8601) | nullEnd date for DATE_RANGE field type.
sourceSystemstringSystem that set this value (e.g. "api", "manual", "integration"). Read-only.
createdAtdatetime (ISO 8601)When the value was created. Read-only.
updatedAtdatetime (ISO 8601)When the value was last modified. Read-only.
definitionobjectThe full definition object. Included in responses.

Values on GET-by-ID

When you fetch an entity by ID (e.g. GET /employees/:id), the response automatically includes a customAttributes array containing all custom attribute values for that entity. You do not need to make a separate request.


Definition Endpoints

MethodPathDescription
GET/org/:orgId/custom-attributesList definitions
GET/org/:orgId/custom-attributes/:definitionIdGet definition
POST/org/:orgId/custom-attributesCreate definition
PATCH/org/:orgId/custom-attributes/:definitionIdUpdate definition
DELETE/org/:orgId/custom-attributes/:definitionIdDelete definition

Permissions

ActionRequired Permission
List / Get definitionssettings_entity_config_view
Create / Update definitionssettings_entity_config_update
Delete definitionssettings_entity_config_delete

List Definitions

GET /org/:orgId/custom-attributes

Returns a paginated list of custom attribute definitions.

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number (1-based).
limitinteger20Records per page. Min 1, max 100.
searchstring--Free-text search across name and description.
sortBystringsortOrderField to sort by: name, createdAt, fieldType, or sortOrder.
sortDirstringascSort direction: asc or desc.
entityTypestring--Filter to definitions that apply to this entity type (e.g. EMPLOYEE).

Example Request

bash
curl -X GET "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/custom-attributes?entityType=EMPLOYEE&limit=50" \
  -H "Authorization: Bearer private_..."

Example Response

json
{
  "data": [
    {
      "id": "clx2d3e4f5g6h7i8j9k0",
      "name": "Cost Centre Code",
      "attributeKey": "cost_centre_code",
      "fieldType": "STRING",
      "entityTypes": ["EMPLOYEE", "CONTRACTOR"],
      "description": "Finance cost centre for budget allocation.",
      "isRequired": false,
      "isActive": true,
      "sortOrder": 0,
      "createdAt": "2026-03-01T10:00:00Z",
      "updatedAt": "2026-03-01T10:00:00Z"
    },
    {
      "id": "clx3e4f5g6h7i8j9k0l1",
      "name": "Compliance Expiry",
      "attributeKey": "compliance_expiry",
      "fieldType": "DATE",
      "entityTypes": ["EMPLOYEE"],
      "description": "Date when the employee's compliance certification expires.",
      "isRequired": true,
      "isActive": true,
      "sortOrder": 1,
      "createdAt": "2026-03-05T14:00:00Z",
      "updatedAt": "2026-03-05T14:00:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 2,
    "hasNextPage": false
  }
}

Get Definition

GET /org/:orgId/custom-attributes/:definitionId

Returns a single custom attribute definition by ID.

Example Request

bash
curl -X GET "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/custom-attributes/clx2d3e4f5g6h7i8j9k0" \
  -H "Authorization: Bearer private_..."

Create Definition

POST /org/:orgId/custom-attributes

Creates a new custom attribute definition.

Create Request Body

FieldTypeRequiredDescription
namestringYesDisplay name. Must be unique within the organization.
attributeKeystringNoMachine key. Must match ^[a-z][a-z0-9_]*$, max 100 characters. Auto-generated from name if omitted.
fieldTypestringYesSTRING, NUMBER, DATE, or DATE_RANGE.
entityTypesstring[]YesAt least one of: EMPLOYEE, TEAM, PROJECT, VACANCY, CONTRACTOR.
descriptionstring | nullNoDescription of the attribute.
isRequiredbooleanNoDefault: false.
isActivebooleanNoDefault: true.
sortOrderintegerNoDefault: 0.

Example Request

bash
curl -X POST "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/custom-attributes" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cost Centre Code",
    "fieldType": "STRING",
    "entityTypes": ["EMPLOYEE", "CONTRACTOR"],
    "description": "Finance cost centre for budget allocation."
  }'

Example Response

json
{
  "data": {
    "id": "clx2d3e4f5g6h7i8j9k0",
    "name": "Cost Centre Code",
    "attributeKey": "cost_centre_code",
    "fieldType": "STRING",
    "entityTypes": ["EMPLOYEE", "CONTRACTOR"],
    "description": "Finance cost centre for budget allocation.",
    "isRequired": false,
    "isActive": true,
    "sortOrder": 0,
    "createdAt": "2026-04-08T09:00:00Z",
    "updatedAt": "2026-04-08T09:00:00Z"
  }
}

Status: 201 Created

attributeKey auto-generation

If you omit attributeKey, it is generated from the name -- for example, "Cost Centre Code" becomes "cost_centre_code". Uniqueness within the organization is guaranteed automatically.


Update Definition

PATCH /org/:orgId/custom-attributes/:definitionId

Updates one or more fields on an existing definition. Only include the fields you want to change.

Update Request Body

FieldTypeRequiredDescription
namestringNoUpdated display name.
fieldTypestringNoUpdated data type.
entityTypesstring[]NoUpdated entity types (min 1).
descriptionstring | nullNoUpdated description.
isRequiredbooleanNoUpdated required flag.
isActivebooleanNoUpdated active flag.
sortOrderintegerNoUpdated sort order.

Example Request

bash
curl -X PATCH "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/custom-attributes/clx2d3e4f5g6h7i8j9k0" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Finance cost centre code — required for all permanent staff.",
    "isRequired": true,
    "entityTypes": ["EMPLOYEE", "CONTRACTOR", "VACANCY"]
  }'

Delete Definition

DELETE /org/:orgId/custom-attributes/:definitionId

Deletes a custom attribute definition and all associated values across all entities. This cannot be undone.

Example Request

bash
curl -X DELETE "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/custom-attributes/clx2d3e4f5g6h7i8j9k0" \
  -H "Authorization: Bearer private_..."

Example Response

json
{
  "data": {
    "id": "clx2d3e4f5g6h7i8j9k0",
    "deleted": true
  }
}

Status: 200 OK

Cascading delete

Deleting a definition permanently removes every value that references it, across all entity types. This cannot be undone.


Value Endpoints

Custom attribute values are managed as a sub-resource on each entity type. The same endpoint pattern applies to all five entity types:

MethodPathDescription
GET/org/:orgId/employees/:id/custom-attributesList values for an employee
PUT/org/:orgId/employees/:id/custom-attributes/:definitionIdSet value on an employee
DELETE/org/:orgId/employees/:id/custom-attributes/:definitionIdRemove value from an employee

Replace employees/:id with any of:

  • contractors/:id
  • vacancies/:id
  • teams/:id
  • projects/:id

Permissions

ActionRequired Permission
List valuesInherits from parent entity access
Set / Remove valuessettings_entity_config_update

List Values for Entity

GET /org/:orgId/employees/:id/custom-attributes

Returns all custom attribute values for the specified entity, ordered by definition sort order. The response is a flat array (not paginated).

Example Request

bash
curl -X GET "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/employees/clx1a2b3c4d5e6f7g8h9/custom-attributes" \
  -H "Authorization: Bearer private_..."

Example Response

json
{
  "data": [
    {
      "id": "clx8v9w0x1y2z3a4b5c6",
      "definitionId": "clx2d3e4f5g6h7i8j9k0",
      "entityType": "EMPLOYEE",
      "entityId": "clx1a2b3c4d5e6f7g8h9",
      "stringValue": "ENG-001",
      "numberValue": null,
      "dateValue": null,
      "dateRangeStart": null,
      "dateRangeEnd": null,
      "sourceSystem": "api",
      "createdAt": "2026-04-08T10:00:00Z",
      "updatedAt": "2026-04-08T10:00:00Z",
      "definition": {
        "id": "clx2d3e4f5g6h7i8j9k0",
        "name": "Cost Centre Code",
        "attributeKey": "cost_centre_code",
        "fieldType": "STRING",
        "entityTypes": ["EMPLOYEE", "CONTRACTOR"],
        "description": "Finance cost centre for budget allocation.",
        "isRequired": false,
        "isActive": true,
        "sortOrder": 0
      }
    }
  ]
}

Set Value (Upsert)

PUT /org/:orgId/employees/:id/custom-attributes/:definitionId

Sets a custom attribute value on an entity. If a value already exists for this definition and entity, it is updated. If not, a new value is created.

Request Body

Provide the value field that matches the definition's fieldType. All value fields are nullable -- set to null to clear a value while keeping the record.

FieldTypeDescription
stringValuestring | nullValue for STRING definitions.
numberValuenumber | nullValue for NUMBER definitions.
dateValuedatetime (ISO 8601) | nullValue for DATE definitions.
dateRangeStartdatetime (ISO 8601) | nullStart date for DATE_RANGE definitions.
dateRangeEnddatetime (ISO 8601) | nullEnd date for DATE_RANGE definitions.

Example: Set a STRING value

bash
curl -X PUT "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/employees/clx1a2b3c4d5e6f7g8h9/custom-attributes/clx2d3e4f5g6h7i8j9k0" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "stringValue": "ENG-001"
  }'

Example: Set a NUMBER value

bash
curl -X PUT "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/projects/clx7p8r9q0s1t2u3v4w5/custom-attributes/clx4f5g6h7i8j9k0l1m2" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "numberValue": 42.5
  }'

Example: Set a DATE_RANGE value

bash
curl -X PUT "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/employees/clx1a2b3c4d5e6f7g8h9/custom-attributes/clx5g6h7i8j9k0l1m2n3" \
  -H "Authorization: Bearer private_..." \
  -H "Content-Type: application/json" \
  -d '{
    "dateRangeStart": "2026-01-01T00:00:00Z",
    "dateRangeEnd": "2026-12-31T23:59:59Z"
  }'

Example Response

json
{
  "data": {
    "id": "clx8v9w0x1y2z3a4b5c6",
    "definitionId": "clx2d3e4f5g6h7i8j9k0",
    "entityType": "EMPLOYEE",
    "entityId": "clx1a2b3c4d5e6f7g8h9",
    "stringValue": "ENG-001",
    "numberValue": null,
    "dateValue": null,
    "dateRangeStart": null,
    "dateRangeEnd": null,
    "sourceSystem": "api",
    "createdAt": "2026-04-08T10:00:00Z",
    "updatedAt": "2026-04-08T10:00:00Z",
    "definition": {
      "id": "clx2d3e4f5g6h7i8j9k0",
      "name": "Cost Centre Code",
      "attributeKey": "cost_centre_code",
      "fieldType": "STRING"
    }
  }
}

Entity type validation

The definition's entityTypes must include the entity type you're setting the value on. For example, if a definition has entityTypes: ["EMPLOYEE", "CONTRACTOR"], you cannot set it on a project. The API returns 400 with a descriptive error.


Remove Value

DELETE /org/:orgId/employees/:id/custom-attributes/:definitionId

Removes a custom attribute value from an entity.

Example Request

bash
curl -X DELETE "https://{tenant}.flowstate.inc/api/v1/org/{orgId}/employees/clx1a2b3c4d5e6f7g8h9/custom-attributes/clx2d3e4f5g6h7i8j9k0" \
  -H "Authorization: Bearer private_..."

Example Response

json
{
  "data": {
    "definitionId": "clx2d3e4f5g6h7i8j9k0",
    "entityId": "clx1a2b3c4d5e6f7g8h9",
    "deleted": true
  }
}

Status: 200 OK


Error Responses

Validation Error (400)

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed.",
    "details": [
      { "field": "entityTypes", "message": "At least one entity type is required" }
    ],
    "errorId": "err_clx9a8b7c6d5e4f3"
  }
}

Entity Type Mismatch (400)

Returned when setting a value on an entity type the definition does not support:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Custom attribute \"Cost Centre Code\" does not apply to entity type PROJECT. Allowed: EMPLOYEE, CONTRACTOR",
    "errorId": "err_clx9a8b7c6d5e4f3"
  }
}

Not Found (404)

json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Custom attribute definition not found: clx2d3e4f5g6h7i8j9k0",
    "errorId": "err_clx9a8b7c6d5e4f3"
  }
}

  • Employees -- Employee records that can have custom attributes.
  • Contractors -- Contractor records that can have custom attributes.
  • Vacancies -- Vacancy records that can have custom attributes.
  • Teams -- Team records that can have custom attributes.
  • Projects -- Project records that can have custom attributes.
  • Custom Integrations Data Model -- Syncing custom attributes via integration hooks.

Flowstate Documentation