Tasks

Manage tasks. Tasks can be assigned to users and linked to companies, contacts, and deals.

List tasks

get

Returns tasks the user has access to. Filter by workspace using the where parameter: {"workspaceId": "<WORKSPACE_UUID>"}.

Common filters:

  • Open tasks: {"workspaceId": "<WS>", "done": false}

  • Tasks for a contact: {"workspaceId": "<WS>", "contactIds": {"$overlaps": ["<CONTACT_UUID>"]}}

  • Tasks by deadline: {"workspaceId": "<WS>", "deadline": {"$gte": "now()"}}

Authorizations
AuthorizationstringRequired

All API requests require a Bearer token in the Authorization header. Contact the Zero team to obtain your API token.

Query parameters
fieldsstringOptional

Comma-separated list of fields to return. Defaults to all fields.

Example: id,name,domain
wherestringOptional

JSON-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 select and multiselect columns, option values are UUIDs (the key field from the column's options array). 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"}
}
Example: {"stage":"<PIPELINE_STAGE_UUID>"}
limitintegerOptional

Maximum number of records to return

Default: 100
offsetintegerOptional

Pagination offset

Default: 0
orderBystringOptional

JSON string for sort order

Example: {"name":"asc"}
Responses
chevron-right
200

Successful response

application/json
totalintegerOptional
get
/api/tasks

Create a task

post

Create a new task in a workspace.

content vs description

Tasks have two Tiptap fields with distinct purposes:

  • content — The task title as a Tiptap document. If omitted, it is automatically generated from the name field.

  • description — Extended notes or context for the task. Supports rich formatting including headings, bullet lists, and task lists. Optional.

Tiptap document format

Both content and description use the same Tiptap document structure:

{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{"type": "text", "text": "Your text here"}]
    }
  ]
}

Rich formatting example with headings, bold text, bullet lists and task lists:

{
  "type": "doc",
  "content": [
    {
      "type": "heading",
      "attrs": {"level": 3},
      "content": [{"type": "text", "text": "Goal"}]
    },
    {
      "type": "paragraph",
      "content": [
        {"type": "text", "text": "Complete the "},
        {"type": "text", "text": "onboarding proposal", "marks": [{"type": "bold"}]},
        {"type": "text", "text": " before Friday."}
      ]
    },
    {
      "type": "taskList",
      "content": [
        {
          "type": "taskItem",
          "attrs": {"checked": false},
          "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Review requirements"}]}]
        },
        {
          "type": "taskItem",
          "attrs": {"checked": false},
          "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Draft document"}]}]
        }
      ]
    },
    {
      "type": "bulletList",
      "content": [
        {
          "type": "listItem",
          "content": [{"type": "paragraph", "content": [{"type": "text", "text": "Keep it concise"}]}]
        }
      ]
    }
  ]
}

Priority

Value
Label

null

No priority

1

Low

2

Medium

3

High

4

Urgent

Linking records

Tasks can be linked to multiple companies, contacts, and deals simultaneously via companyIds, contactIds, and dealIds.

⚠️ Important: When updating array fields via PATCH, the entire array is replaced — not merged. Always include all desired IDs when patching these fields.

Authorizations
AuthorizationstringRequired

All API requests require a Bearer token in the Authorization header. Contact the Zero team to obtain your API token.

Body
workspaceIdstring · uuidRequired
namestringRequired

Title of the task. Also used to auto-generate content if content is not provided.

contentobjectOptional

Task title as a Tiptap document. If omitted, auto-generated from name.

descriptionobjectOptional

Extended notes in Tiptap document format. Supports headings, bullet lists, task lists, and inline formatting.

donebooleanOptionalDefault: false
priorityinteger · enum · nullableOptional

null = No priority, 1 = Low, 2 = Medium, 3 = High, 4 = Urgent

Possible values:
deadlinestring · date-timeOptional
companyIdsstring · uuid[]Optional
contactIdsstring · uuid[]Optional
dealIdsstring · uuid[]Optional
assignedToIdsstring · uuid[]Optional
externalIdstringOptional
sourcestringOptional
Responses
chevron-right
200

Task created successfully

application/json
post
/api/tasks

Get a task

get

Retrieve a single task by ID.

If the task does not exist, the API returns HTTP 200 with an empty body ({}).

Authorizations
AuthorizationstringRequired

All API requests require a Bearer token in the Authorization header. Contact the Zero team to obtain your API token.

Path parameters
taskIdstring · uuidRequired
Responses
chevron-right
200

Successful response

application/json
get
/api/tasks/{taskId}

Delete a task

delete

Delete a task. Use archive=true for soft delete (recoverable), or omit for permanent deletion.

Authorizations
AuthorizationstringRequired

All API requests require a Bearer token in the Authorization header. Contact the Zero team to obtain your API token.

Path parameters
taskIdstring · uuidRequired
Query parameters
archivebooleanOptional

If true, soft deletes (archives) the task instead of permanently deleting it.

Default: false
Responses
chevron-right
200

Task deleted successfully

application/json
dataone ofOptional

Hard delete (archive omitted or false): returns 1 on success. Soft delete (archive=true): returns a single-element array containing the archived task object.

integerOptionalExample: 1
or
delete
/api/tasks/{taskId}

Update a task

patch

Update an existing task.

Note: The response only returns the fields that were changed — not the full task object.

⚠️ Important: Array fields (contactIds, companyIds, dealIds, assignedToIds) are replaced on PATCH, not merged. Always include all desired IDs.

To mark a task as complete: {"done": true}

Authorizations
AuthorizationstringRequired

All API requests require a Bearer token in the Authorization header. Contact the Zero team to obtain your API token.

Path parameters
taskIdstring · uuidRequired
Body

All fields are optional. Array fields (contactIds, companyIds, dealIds, assignedToIds) replace the existing array entirely on update.

namestringOptional
contentobjectOptional

Replaces the entire task content. Must be a valid Tiptap document.

descriptionobjectOptional

Replaces the entire description. Must be a valid Tiptap document.

donebooleanOptional
priorityinteger · enum · nullableOptionalPossible values:
deadlinestring · date-time · nullableOptional
companyIdsstring · uuid[]Optional
contactIdsstring · uuid[]Optional
dealIdsstring · uuid[]Optional
assignedToIdsstring · uuid[]Optional
externalIdstringOptional
sourcestringOptional
Responses
chevron-right
200

Task updated successfully. Only the fields that were changed are returned in data.

application/json
dataobjectOptional

Partial task object containing only the updated fields plus updatedAt and updatedById.

patch
/api/tasks/{taskId}

Last updated