Columns
Manage custom property definitions (called columns in the API) for companies, contacts, and deals. Use GET /api/columns to discover the IDs, types, and options of custom fields before filtering or updating records, and POST / PATCH / DELETE to create, edit, and remove properties.
Definitions vs. values
A column is the definition of a custom property — its name, type, options, and which entity it belongs to. The values live on the records themselves, in the custom object of each company / contact / deal, keyed by the column's id. Creating a column does not touch any records; it just makes custom.<column-id> available for writes, filters, views, and reports.
Column Company record
{ "id": "54e1ca7d-…", { "id": "…",
"entity": "companies", "name": "Acme",
"name": "Industry", "custom": {
"type": "select", "54e1ca7d-…": "3e839b5c-…" ← option key
"options": [ {"key": "3e839b5c-…", "name": "SaaS"}, … ] } }
}Creating a property
POST /api/columns with at least workspaceId, entity, name, and type. For select / multiselect, also pass options — every option needs a client-generated UUID in key; that UUID is what gets stored on records, so it must stay stable for the life of the option. Names and colors can be edited freely later.
Editing a property
PATCH /api/columns/{columnId}. Renaming, changing the description, and editing options are safe. Note that options is replaced wholesale on write — always send the complete list. Removing an option from options does not delete it from records; move it to archivedOptions instead so existing values keep resolving to a name. Changing type is allowed for a limited set of pairs and triggers a background migration of existing values — see PATCH for the supported conversions.
Deleting a property
DELETE /api/columns/{columnId} permanently removes the definition. Values already stored under that id on records are not cleaned up — they simply become invisible/orphaned. Prefer DELETE …?archive=true (soft delete) when you may need to restore the property; restore with PATCH {"archived": false}.
Reserved / built-in fields
Only user-defined properties are columns. Built-in fields (name, domain, stage, value, …) are top-level record fields, not columns, and cannot be created or deleted through this endpoint.
Returns the custom property (column) definitions for a workspace. Filter by workspace using the where parameter: {"workspaceId": "<WORKSPACE_UUID>"}. Strongly recommended — omitting it returns columns across all workspaces the user has access to.
Use this endpoint to discover the IDs, types, and available options of custom fields before filtering or updating records.
Custom properties are stored in the custom object on companies, contacts, and deals. Each custom property is keyed by its UUID (id from this response).
For example, if this endpoint returns a column with "id": "54e1ca7d-69c3-4b77-8266-8085b5834116" and "type": "select", you can:
Filter records using:
{"custom.54e1ca7d-69c3-4b77-8266-8085b5834116": {"$in": ["<OPTION_KEY_UUID>", "<OPTION_KEY_UUID>"]}}Update a record using:
{"custom.54e1ca7d-69c3-4b77-8266-8085b5834116": "<OPTION_KEY_UUID>"}
Note: For
selectandmultiselectcolumns, option values are UUIDs stored in thekeyfield of each option object. Use thekeyUUID (not the human-readablename) when filtering or updating records.
All API requests require a Bearer token in the Authorization header. Create an API key from Workspace Settings → API keys
Comma-separated list of fields to return. Defaults to all fields.
Supports relation expansion with dot-notation: a path like company.name embeds the named field of the related record, and quotes.id embeds the id of each related quote. Use .* to embed full related objects, e.g. quotes.*. Related records are returned nested on the response — as an object for to-one relations (e.g. company) or an array for to-many relations (e.g. quotes). Archived related records are excluded.
Example: GET /api/deals/{dealId}?fields=id,name,quotes.id returns the deal with a quotes array of {"id": "<QUOTE_UUID>"} entries.
id,name,domainJSON-encoded filter object. All top-level conditions are combined with AND logic. Use $or for OR logic.
The available operators depend on the data type of the field you are filtering on.
String fields
Fields like name, domain, description, linkedin, source, externalId, location.
| Operator | Description | Example |
|---|---|---|
| (exact) | Exact match | {"name": "Linear"} |
$eq | Explicit exact match | {"name": {"$eq": "Linear"}} |
$not | Not equal | {"source": {"$not": "import"}} |
$in | Matches any value in array | {"domain": {"$in": ["linear.app", "granola.so"]}} |
$notIn | Matches none of the values | {"source": {"$notIn": ["import", "api"]}} |
$contains | Case-insensitive word-boundary substring match | {"name": {"$contains": "YC"}} |
$notContains | Does not contain | {"name": {"$notContains": "Test"}} |
$containsAny | Contains any of the given strings | {"name": {"$containsAny": ["YC", "Techstars"]}} |
$startsWith | Starts with prefix | {"domain": {"$startsWith": "app."}} |
$endsWith | Ends with suffix | {"email": {"$endsWith": "@zero.inc"}} |
$exists | Field is present and truthy | {"linkedin": {"$exists": true}} |
$notExists | Field is absent, null, or empty | {"linkedin": {"$notExists": true}} |
Number fields
Fields like value, confidence.
| Operator | Description | Example |
|---|---|---|
| (exact) | Exact match | {"value": 5000} |
$eq | Explicit exact match | {"value": {"$eq": 5000}} |
$not | Not equal | {"value": {"$not": 0}} |
$gt | Greater than | {"value": {"$gt": 10000}} |
$gte | Greater than or equal | {"value": {"$gte": 5000}} |
$lt | Less than | {"value": {"$lt": 10000}} |
$lte | Less than or equal | {"value": {"$lte": 50000}} |
$in | Matches any value in array | {"confidence": {"$in": [0.25, 0.5, 0.75]}} |
$notIn | Matches none of the values | {"confidence": {"$notIn": [0, 1]}} |
$exists | Field is present and truthy | {"value": {"$exists": true}} |
$notExists | Field is absent, null, or zero | {"value": {"$notExists": true}} |
Multiple operators can be combined on one field:
{"value": {"$gte": 5000, "$lt": 10000}}
Date fields
Fields like closeDate, startDate, endDate, createdAt, updatedAt.
Values can be ISO 8601 strings ("2026-01-01", "2026-01-01T00:00:00Z") or relative time macros.
Relative time macros: +Nd / -Nd (days), +Nw / -Nw (weeks), +Nm / -Nm (months), +Ny / -Ny (years), +Nh / -Nh (hours), +Ns / -Ns (seconds), now().
| Operator | Description | Example |
|---|---|---|
$gte | On or after | {"closeDate": {"$gte": "2026-01-01"}} |
$lte | On or before | {"closeDate": {"$lte": "2026-03-31"}} |
$gt | After | {"createdAt": {"$gt": "2026-01-01T00:00:00Z"}} |
$lt | Before | {"createdAt": {"$lt": "now()"}} |
$date | Exact date match (compares date portion only) | {"closeDate": {"$date": "2026-01-15"}} |
$exists | Field is present and truthy | {"closeDate": {"$exists": true}} |
$notExists | Field is absent or null | {"closeDate": {"$notExists": true}} |
Date range example:
{"closeDate": {"$gte": "2026-01-01", "$lte": "2026-03-31"}}
Relative date example (closing in next 30 days):
{"closeDate": {"$gte": "now()", "$lte": "+30d"}}
Array fields
Fields like listIds, ownerIds, contactIds.
| Operator | Description | Example |
|---|---|---|
$includes | Array contains the given value (use this — bare exact match is not supported) | {"listIds": {"$includes": "<LIST_UUID>"}} |
$notIncludes | Array does not contain the given value | {"ownerIds": {"$notIncludes": "<USER_UUID>"}} |
$overlaps | Array contains at least one of the given values | {"ownerIds": {"$overlaps": ["<UUID_1>", "<UUID_2>"]}} |
$notOverlaps | Array contains none of the given values | {"listIds": {"$notOverlaps": ["<UUID_1>", "<UUID_2>"]}} |
$all | Array contains all of the given values | {"listIds": {"$all": ["<UUID_1>", "<UUID_2>"]}} |
$length | Filter by array length (supports nested operators) | {"contactIds": {"$length": {"$gte": 2}}} |
$exists | Field is present and non-empty | {"ownerIds": {"$exists": true}} |
$notExists | Field is absent or empty | {"ownerIds": {"$notExists": true}} |
UUID / ID fields
Fields like id, workspaceId, companyId, stage.
| Operator | Description | Example |
|---|---|---|
| (exact) | Exact match | {"stage": "<PIPELINE_STAGE_UUID>"} |
$in | Matches any value in array | {"stage": {"$in": ["<UUID_1>", "<UUID_2>"]}} |
$notIn | Matches none of the values | {"stage": {"$notIn": ["<UUID_1>"]}} |
$not | Not equal | {"stage": {"$not": "<UUID>"}} |
Boolean fields
Fields like archived.
| Operator | Description | Example |
|---|---|---|
| (exact) | Exact match | {"archived": false} |
$not | Not equal | {"archived": {"$not": true}} |
Logical operators
These work across all data types.
$or — matches if any sub-condition is true:
{
"workspaceId": "<WORKSPACE_UUID>",
"$or": [
{"ownerIds": {"$overlaps": ["<USER_UUID_1>", "<USER_UUID_2>"]}},
{"closeDate": {"$gte": "2026-01-01"}}
]
}
$and — matches if all sub-conditions are true (useful when you need multiple conditions on the same field):
{
"$and": [
{"name": {"$contains": "Enterprise"}},
{"name": {"$notContains": "Test"}}
]
}
Dot-notation (relation filtering)
Use dot-syntax to filter records based on properties of related objects:
{"company.name": "Linear"}
{"company.domain": {"$in": ["linear.app", "granola.so"]}}
{"company.location.city": "San Francisco"}
{"companyProfile.categories": {"$overlaps": ["Sales", "Marketing"]}}
All operators available for the target field's data type can be used with dot-notation.
Custom property filtering
Custom properties are stored in the custom object on records, keyed by UUID. Use GET /api/columns to discover the available custom property IDs, types, and options for a workspace.
Filter on custom properties using custom.<COLUMN_ID> with operators appropriate for the column's type.
Note: For
selectandmultiselectcolumns, option values are UUIDs (thekeyfield from the column'soptionsarray). Use the UUID, not the human-readable name.
// Text custom property
{"custom.54e1ca7d-69c3-4b77-8266-8085b5834116": {"$contains": "enterprise"}}
// Select custom property (use the option key UUID)
{"custom.a1b2c3d4-e5f6-7890-abcd-ef1234567890": "3e839b5c-b311-4887-b2da-727d2d75cdd6"}
// Multi-select custom property (use option key UUIDs)
{"custom.b2c3d4e5-f6a7-8901-bcde-f12345678901": {"$overlaps": ["a1b1c1d1-e1f1-1111-aaaa-111111111111", "b2b2c2d2-e2f2-2222-bbbb-222222222222"]}}
// Currency/number custom property
{"custom.c3d4e5f6-a7b8-9012-cdef-123456789012": {"$gte": 100000}}
// Date custom property
{"custom.d4e5f6a7-b8c9-0123-defa-234567890123": {"$gte": "2026-01-01"}}
// Boolean custom property
{"custom.e5f6a7b8-c9d0-1234-efab-345678901234": true}
// Check if custom property has a value
{"custom.f6a7b8c9-d0e1-2345-fabc-456789012345": {"$exists": true}}
Complex example
All top-level keys are ANDed together:
{
"name": {"$contains": "Zero"},
"location.city": "Helsinki",
"location.country": {"$in": ["United Kingdom", "Germany", "Sweden"]},
"value": {"$gte": 10000},
"closeDate": {"$gte": "2026-01-01", "$lte": "2026-03-31"},
"ownerIds": {"$includes": "<USER_UUID>"},
"stage": {"$in": ["<UUID_1>", "<UUID_2>"]},
"lastActivity": {"$exists": true},
"companyProfile.categories": {"$overlaps": ["Sales", "Marketing"]},
"custom.54e1ca7d-69c3-4b77-8266-8085b5834116": {"$contains": "enterprise"}
}
{"stage":"<PIPELINE_STAGE_UUID>"}Maximum number of records to return
100Pagination offset
0JSON string for sort order
{"name":"asc"}Successful response
Total number of custom property definitions
Authentication failed or token is invalid/expired
GET /api/columns HTTP/1.1
Host: api.zero.inc
Authorization: Bearer YOUR_API_TOKEN
Accept: */*
{
"data": [
{
"id": "54e1ca7d-69c3-4b77-8266-8085b5834116",
"workspaceId": "dd66c03b-1a84-4c9d-b118-3cc54e21d019",
"name": "Industry",
"type": "select",
"entity": "companies",
"options": [
{
"key": "3e839b5c-b311-4887-b2da-727d2d75cdd6",
"name": "SaaS",
"color": "#4CAF50"
},
{
"key": "7f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Fintech",
"color": "#2196F3"
}
]
},
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"workspaceId": "dd66c03b-1a84-4c9d-b118-3cc54e21d019",
"name": "ARR",
"type": "currency",
"entity": "companies",
"options": null
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"workspaceId": "dd66c03b-1a84-4c9d-b118-3cc54e21d019",
"name": "Tags",
"type": "multiselect",
"entity": "deals",
"options": [
{
"key": "a1b1c1d1-e1f1-1111-aaaa-111111111111",
"name": "Enterprise",
"color": "#FF9800"
},
{
"key": "b2b2c2d2-e2f2-2222-bbbb-222222222222",
"name": "Strategic",
"color": "#9C27B0"
}
]
}
],
"total": 3
}Create a new custom property definition on companies, contacts, or deals. The property immediately becomes available for filtering, views, reports, and for writing values into custom.<column-id> on records of that entity.
Always send workspaceId, entity, name, and type.
No server-side validation. The API does not validate these fields or the
type/entityenums. OmittingtypeorworkspaceIdfails with a500 Database insert query failed; omittingnameorentity, or sending an unknowntype/entity, succeeds and silently creates a definition the app cannot render. Values written tocustom.<column-id>on records are likewise stored as sent, without being checked against the column type — the per-type table onColumndescribes what the app, filters, and reports expect, not an enforced contract.
Select / multiselect options
For select and multiselect types, pass the initial options in options. Each option's key must be a UUID that you generate — it becomes the value stored on records, so it must be unique within the column and stable over time. name is the display label; color is an optional hex color.
{
"workspaceId": "dd66c03b-1a84-4c9d-b118-3cc54e21d019",
"entity": "companies",
"name": "Industry",
"type": "select",
"options": [
{ "key": "3e839b5c-b311-4887-b2da-727d2d75cdd6", "name": "SaaS", "color": "#4CAF50" },
{ "key": "7f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "name": "Fintech", "color": "#2196F3" }
]
}Using the new property on records
The response contains the column id. Write values with dot-notation on the record — never by replacing the whole custom object:
curl -X PATCH "https://api.zero.inc/api/companies/COMPANY_UUID" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"custom.54e1ca7d-69c3-4b77-8266-8085b5834116": "3e839b5c-b311-4887-b2da-727d2d75cdd6"}'See the type field on Column for the value shape each type expects. The PATCH response echoes only the touched sub-key ("custom": {"<column-id>": value}), not the whole custom object — other keys are preserved; re-GET the record if you need the merged object. Setting a value to null keeps the key in custom with a null value rather than removing it.
AI properties
Set ai: true together with aiPrompt to create an AI-filled property. AI properties are configured most reliably in the app; the API accepts the fields but does not validate the prompt structure.
All API requests require a Bearer token in the Authorization header. Create an API key from Workspace Settings → API keys
Which record type the property is added to. Not validated server-side — other values are stored but unusable. Do not change it later.
Display name of the property.
Optional help text shown in the app.
The data type. See the type table on Column for the value shape each type stores on records.
Type-specific display settings. Omit unless you know you need it.
Set true to create an AI-filled property. Requires aiPrompt.
falsePrompt document for AI-filled properties. Easiest to author in the app and copy from an existing AI column.
Data sources the AI may use, e.g. {"scraping": false, "emails": false, "calendarEvents": false, "linkedinMessages": false, "files": false, "notes": false}.
Events that re-run the AI property.
Custom property created successfully
Authentication failed or token is invalid/expired
POST /api/columns HTTP/1.1
Host: api.zero.inc
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 324
{
"workspaceId": "dd66c03b-1a84-4c9d-b118-3cc54e21d019",
"entity": "companies",
"name": "Industry",
"description": "Primary industry vertical",
"type": "select",
"options": [
{
"key": "3e839b5c-b311-4887-b2da-727d2d75cdd6",
"name": "SaaS",
"color": "#4CAF50"
},
{
"key": "7f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Fintech",
"color": "#2196F3"
}
]
}{
"data": {
"id": "54e1ca7d-69c3-4b77-8266-8085b5834116",
"workspaceId": "dd66c03b-1a84-4c9d-b118-3cc54e21d019",
"entity": "companies",
"name": "Industry",
"description": "Primary industry vertical",
"type": "select",
"options": [
{
"key": "3e839b5c-b311-4887-b2da-727d2d75cdd6",
"name": "SaaS",
"color": "#4CAF50"
},
{
"key": "7f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Fintech",
"color": "#2196F3"
}
],
"archivedOptions": null,
"ai": false,
"archived": false,
"createdAt": "2026-08-17T09:12:44.000Z",
"updatedAt": "2026-08-17T09:12:44.000Z"
},
"sideEffects": []
}Returns a single custom property definition by ID.
An unknown or deleted ID returns 200 with an empty data object ({}), not a 404.
All API requests require a Bearer token in the Authorization header. Create an API key from Workspace Settings → API keys
Comma-separated list of fields to return. Defaults to all fields.
Supports relation expansion with dot-notation: a path like company.name embeds the named field of the related record, and quotes.id embeds the id of each related quote. Use .* to embed full related objects, e.g. quotes.*. Related records are returned nested on the response — as an object for to-one relations (e.g. company) or an array for to-many relations (e.g. quotes). Archived related records are excluded.
Example: GET /api/deals/{dealId}?fields=id,name,quotes.id returns the deal with a quotes array of {"id": "<QUOTE_UUID>"} entries.
id,name,domainSuccessful response
Authentication failed or token is invalid/expired
GET /api/columns/{columnId} HTTP/1.1
Host: api.zero.inc
Authorization: Bearer YOUR_API_TOKEN
Accept: */*
{
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"workspaceId": "123e4567-e89b-12d3-a456-426614174000",
"entity": "companies",
"name": "text",
"description": "text",
"key": "text",
"type": "text",
"options": [
{
"key": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"color": "text"
}
],
"archivedOptions": [
{
"key": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"color": "text"
}
],
"settings": {},
"ai": true,
"aiPrompt": {},
"aiSettings": {},
"aiTriggers": [
"text"
],
"source": "text",
"externalId": "text",
"importId": "123e4567-e89b-12d3-a456-426614174000",
"aiContextIds": [
"123e4567-e89b-12d3-a456-426614174000"
],
"archived": true,
"archivedAt": "2026-01-01T00:00:00.000Z",
"archivedById": "123e4567-e89b-12d3-a456-426614174000",
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z",
"createdById": "123e4567-e89b-12d3-a456-426614174000",
"updatedById": "123e4567-e89b-12d3-a456-426614174000"
}
}Remove a custom property definition.
Permanent delete (default)
DELETE /api/columns/{columnId} permanently deletes the definition. Returns {"data": 1} on success and {"data": 0} when no matching non-archived column exists. There is no undo.
Soft delete (archive)
DELETE /api/columns/{columnId}?archive=true sets archived: true instead. The response is {"data": [<archived column>]} — an array containing the full row with archived: true, archivedAt, and archivedById set (or [] if nothing was archived). Archived columns are hidden from the app and excluded from default GET /api/columns results; GET /api/columns/{columnId} returns 200 {} for them. List them with {"archived": true} in where, and restore with PATCH /api/columns/{columnId} {"archived": false}. An archived column cannot be hard-deleted directly — DELETE without ?archive=true returns {"data": 0} — restore it first, then delete.
Warning: Deleting a property does not remove its values from records. Any
custom.<column-id>values already stored on companies, contacts, or deals stay in thecustomobject as orphaned keys — they are no longer shown in the app, filters, or reports. Views that reference the column insettings.columnsorfilterskeep the stalecustom.<column-id>reference in their stored JSON; the app simply can no longer resolve it. Theidcannot be re-created, so a new property with the same name will not pick the old values back up.
A non-UUID columnId returns 500, not 404.
All API requests require a Bearer token in the Authorization header. Create an API key from Workspace Settings → API keys
Set to true to soft-delete (archive) instead of permanently deleting. Omit for a permanent delete.
Deletion result. data is an integer for a permanent delete and an array of archived rows when ?archive=true was used.
Permanent delete: 1 if deleted, 0 if not found
Authentication failed or token is invalid/expired
DELETE /api/columns/{columnId} HTTP/1.1
Host: api.zero.inc
Authorization: Bearer YOUR_API_TOKEN
Accept: */*
{
"data": 1,
"sideEffects": []
}Update a custom property definition. Only the fields you send are changed. The response data echoes the fields you sent (even if unchanged) plus id, updatedAt, and updatedById. Unknown fields are silently ignored; an unknown columnId returns 200 with no data rather than a 404.
Renaming / description
Send name and/or description. Values on records are unaffected — they are keyed by the column id, not the name.
Editing options (select / multiselect)
options is replaced as a whole on every write. To add, rename, recolor, or reorder options, send the full desired list. Keep the existing key UUIDs for options that already exist — changing a key orphans every record value that used the old one.
To retire an option without breaking records that still hold it, remove it from options and add it to archivedOptions. Archived options are no longer offered when editing records, but existing values keep resolving to their name. To restore, move it back. Both arrays are replaced wholesale, so send the complete list for each. Option objects are stored as sent — the API does not check that each has a key, so make sure you include one.
{
"options": [
{ "key": "3e839b5c-b311-4887-b2da-727d2d75cdd6", "name": "SaaS", "color": "#4CAF50" },
{ "key": "9c8b7a6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d", "name": "Health", "color": "#E91E63" }
],
"archivedOptions": [
{ "key": "7f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "name": "Fintech", "color": "#2196F3" }
]
}Changing the type
Changing type between the pairs below kicks off a background migration of the values already stored on records. The PATCH returns immediately (before the migration runs; sideEffects stays []), so re-read records afterwards rather than expecting the PATCH response to reflect it. Locally the migration finishes within milliseconds; on large workspaces allow a little longer. Only non-archived records are migrated.
text / number / percentage / boolean / link / currency / email / phone → select or multiselect
Each distinct plain value becomes an option (matched by name against existing active and archived options; new options are appended to options with a generated key and no color); record values are rewritten to the option key.
select / multiselect → any plain type above
Option keys are resolved to the option's name (active or archived). Target text / link / email / phone gets the name; multiselect → text joins multiple names with ", ". Target number / currency / percentage keeps only numeric names, otherwise null. Target boolean maps true/false/yes/no, otherwise null. For multiselect → numeric/boolean only the first value is considered. The options array stays on the definition (it is not cleared).
select → multiselect, user → users, company → companies, contact → contacts, deal → deals, task → tasks
Single values are wrapped in an array (whatever the value is, active or archived option).
The reverse of each pair above
Arrays are collapsed to their first element.
Any other type change (e.g. text → number, select → date) is accepted on the definition but does not migrate values — records keep whatever was stored, which will usually render as empty or invalid under the new type. type is not validated, so a typo is stored as-is. Avoid changes outside the listed pairs.
Fields you should not change
workspaceId and entity are set at creation and must not be changed — values stored under this column id live on the original entity's records and would be orphaned. To move a property between entities, create a new property on the target entity instead.
All API requests require a Bearer token in the Authorization header. Create an API key from Workspace Settings → API keys
Fields that can be patched on a custom property. Send only what you want to change. options and archivedOptions are replaced wholesale — always send the complete list.
New data type. Only the conversions listed on PATCH /api/columns/{columnId} migrate existing record values (plain ↔ select/multiselect, single ↔ multi). Other changes leave record values untouched and usually unusable.
Set false to restore a property that was soft-deleted with DELETE …?archive=true.
Property updated. data contains the fields you sent plus id, updatedAt, and updatedById.
Authentication failed or token is invalid/expired
PATCH /api/columns/{columnId} HTTP/1.1
Host: api.zero.inc
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 85
{
"name": "Industry vertical",
"description": "Primary industry the company operates in"
}{
"data": {
"id": "54e1ca7d-69c3-4b77-8266-8085b5834116",
"name": "Industry vertical",
"description": "Primary industry the company operates in",
"updatedAt": "2026-08-17T11:48:37.281Z",
"updatedById": "b373353e-1a84-4c9d-b118-3cc54e21d019"
},
"sideEffects": []
}Last updated

