Notes

Manage notes attached to companies, contacts, and deals.

List notes

get

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

Notes can also be filtered by contactId, companyId, or dealId to retrieve notes for a specific record.

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/notes

Create a note

post

Create a new note in a workspace. Notes can be associated with a company, contact, or deal (or any combination).

The content field uses the Tiptaparrow-up-right document format β€” a JSON structure with a type: "doc" root node containing an array of block nodes (paragraphs, headings, etc.).

Minimal Tiptap document

An empty note body:

{"type": "doc", "content": []}

Tiptap document with text

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

The content field can be omitted on creation and set later via PATCH.

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
namestringOptional

Title of the note

emojistringOptional

Emoji icon for the note

contentobjectOptional

Note body in Tiptap document format. Can be omitted and set later via PATCH.

companyIdstring Β· uuidOptional

Associate the note with a company

contactIdstring Β· uuidOptional

Associate the note with a contact

dealIdstring Β· uuidOptional

Associate the note with a deal

externalIdstringOptional
sourcestringOptional
Responses
chevron-right
200

Note created successfully

application/json
post
/api/notes

Delete a note

delete

Delete a note. 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
noteIdstring Β· uuidRequired
Query parameters
archivebooleanOptional

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

Default: false
Responses
chevron-right
200

Note 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 note object.

integerOptionalExample: 1
or
delete
/api/notes/{noteId}

Update a note

patch

Update an existing note.

Note: Unlike other PATCH endpoints, the response only returns the fields that were changed β€” not the full note object.

To update the note body, pass a complete Tiptap document in content β€” this replaces the existing content entirely.

Authorizations
AuthorizationstringRequired

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

Path parameters
noteIdstring Β· uuidRequired
Body
namestringOptional
emojistringOptional
contentobjectOptional

Replaces the entire note body. Must be a valid Tiptap document.

companyIdstring Β· uuidOptional
contactIdstring Β· uuidOptional
dealIdstring Β· uuidOptional
externalIdstringOptional
sourcestringOptional
Responses
chevron-right
200

Note updated successfully. Only the fields that were changed are returned in data (not the full note object).

application/json
dataobjectOptional

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

patch
/api/notes/{noteId}

Last updated