Custom fields
List and add your workspace's own fields on jobs, customers, contacts and sites, and read and write their values.
View as MarkdownWorkspaces add their own fields to records: "Gate code" on jobs, "Snow contract" on customers, "Shirt size" on contacts, "Lot size" on sites. A field is defined once per record type and every record of that type can hold a value.
Record types (entity_type):
entity_type |
Records | Values are on |
|---|---|---|
job |
Jobs | GET /v1/jobs/{id} → custom_fields |
account |
Customers (client accounts) | GET /v1/client-accounts/{id} → custom_fields |
contact |
Contacts | GET /v1/contacts/{id} → custom_fields |
location |
Sites (locations) | GET /v1/locations/{id} → custom_fields |
Values are stored under each field's key (a slug of its label, e.g. gate_code). custom_fields is an object of {key: value}; a field with no value is simply missing.
Note
Partner keys that act for several workspaces must also send firm_id (query string, or JSON body on writes).
The field object#
| Field | Type | Description |
|---|---|---|
id |
integer | TruTec id. |
entity_type |
string | job, account, contact or location. |
key |
string | The key values are stored under. Never changes, even when the label is renamed in the app. |
label |
string | What people see. |
field_type |
string | text, number, date, select, checkbox or url. |
options |
array of strings | The choices of a select field. |
required |
boolean | The app asks for it when a record is created. |
filterable |
boolean | Shown as a filter on the jobs board or customer / contact lists. |
show_as_flag |
boolean | Jobs: shown on the job card. |
section |
string | Where the field shows on the record's create / edit screens (see Field setup). |
position |
integer | Order on the record page. |
archived_at, created_at, updated_at |
string or null | UTC with Z. |
Values by type#
field_type |
Send | Stored as |
|---|---|---|
text, url |
a string | the string (up to 500 characters) |
number |
a number or numeric string ("1,250" is fine) |
a number |
date |
"YYYY-MM-DD" |
the same string |
select |
one of options, any case |
the option as spelled in options |
checkbox |
true / false (or "yes" / "no") |
a boolean |
null or "" clears a field.
Fields#
List custom fields#
GET /v1/custom-fields
Permission: Read jobs
| Name | Type | Required | Description |
|---|---|---|---|
entity_type |
string | No | Only one record type. |
include_archived |
boolean | No | Include archived fields (their values stay on records). |
curl "https://trutec.ai/api/v1/custom-fields?entity_type=job" \
-H "X-API-Key: sk_your_api_key_here"
{
"data": [
{
"id": 61,
"entity_type": "job",
"key": "gate_code",
"label": "Gate code",
"field_type": "text",
"options": [],
"required": false,
"filterable": false,
"show_as_flag": false,
"section": "job_location",
"position": 1,
"archived_at": null,
"created_at": "2026-10-12T14:00:00Z",
"updated_at": "2026-10-12T14:00:00Z"
}
]
}
Create a custom field#
POST /v1/custom-fields
Permission: Write jobs
Adds a field to every record of one type. If the type already has a field with the same label (any case), that field is returned instead with 200 and "created": false, and brought back if it was archived.
| Name | Type | Required | Description |
|---|---|---|---|
entity_type |
string | Yes | job, account, contact or location. |
label |
string | Yes | Max 120 characters. |
field_type |
string | No | Default text. |
options |
array of strings | For select |
The choices. |
required |
boolean | No | Ask for it when a record is created in the app. |
filterable |
boolean | No | Jobs, customers and contacts only. |
show_as_flag |
boolean | No | Jobs only. |
curl -X POST "https://trutec.ai/api/v1/custom-fields" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"entity_type": "account", "label": "Service tier", "field_type": "select", "options": ["Gold", "Silver"]}'
Returns 201 with {"data": {field}, "created": true}.
Errors: 400 entity_type must be one of: ..., field_type must be one of: ..., Give the field a name., Add at least one dropdown option.
To rename, reorder, archive or restore a field, see Field setup.
Values#
Set custom fields on a record#
PATCH /v1/jobs/{id}/custom-fields
PATCH /v1/client-accounts/{id}/custom-fields
PATCH /v1/contacts/{id}/custom-fields
PATCH /v1/locations/{id}/custom-fields
Permission: Write jobs
Sets the fields you send and leaves the others alone. Every value is checked first; if any key is unknown or any value is invalid, nothing is saved. On a job, each change is written to the job's activity log as in the app.
| Name | Type | Required | Description |
|---|---|---|---|
custom_fields |
object | Yes | {key: value}. null clears a field. |
curl -X PATCH "https://trutec.ai/api/v1/jobs/41872/custom-fields" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"custom_fields": {"gate_code": "4411#", "snow_contract": true}}'
{
"data": {
"entity_type": "job",
"id": 41872,
"custom_fields": {"gate_code": "4411#", "snow_contract": true},
"changed": ["gate_code", "snow_contract"]
}
}
Errors:
400Unknown custom fields: ...(code: unknown_custom_fields,fieldslists them)400Lot size must be a number.,Choose one of the Service tier options.and the like (code: invalid_custom_field,fieldnames it)404for a record outside the workspace
Contacts also accept custom_fields on POST /v1/contacts and PATCH /v1/contacts/{id} (see Contacts).
Field setup#
Change a field the way Settings › Custom fields does. Only workspace owners change field setup, as in the app: a key created by anyone else gets 403. Values already stored on records are never touched.
section values by record type:
entity_type |
section |
|---|---|
job |
job_location, company_contact, job_details |
account |
company_profile, billing, company_notes |
contact |
contact_identity, communication, contact_notes |
location |
location_identity, property_context, location_notes |
Update a custom field#
PATCH /v1/custom-fields/{id}
Permission: Write jobs (owner key)
Only the fields you send change.
| Name | Type | Description |
|---|---|---|
label |
string | New name, up to 120 characters. The key stays the same, so values keep working. |
required |
boolean | Ask for it when a record is created in the app. |
section |
string | Where it shows on the create / edit screens (table above). |
show_as_flag |
boolean | Job fields only. Show it on the job card. |
filterable |
boolean | Job fields only. A filter on the jobs board. |
curl -X PATCH "https://trutec.ai/api/v1/custom-fields/61" \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"label": "Gate / lockbox code", "required": true}'
Returns 200 with {"data": {field}}.
Errors: 400 A field named "..." already exists., show_as_flag can only be changed on job fields, section must be one of: ...; 403 when the key's creator is not a workspace owner.
Move a custom field#
POST /v1/custom-fields/{id}/move
Permission: Write jobs (owner key)
Send {"direction": "up"} or {"direction": "down"} to move the field one place among its type's active fields. position is renumbered from 1 for the whole type. Returns 200 with {"data": {field}}. An archived field returns 409 archived.
Archive a custom field#
DELETE /v1/custom-fields/{id}
Permission: Write jobs and Delete records (owner key)
Archives the field on every record of its type. Nothing is deleted: values stay stored and show read-only on the records that have them, and restoring brings the field back. Returns 204.
Restore a custom field#
POST /v1/custom-fields/{id}/restore
Permission: Write jobs (owner key)
Brings an archived field back, with the values it had. Returns 200 with {"data": {field}}.