# Custom Activity Types

Manage activity type definitions for a workspace. Each workspace comes with default types (Call, Meeting) and supports creating additional custom types.

## List custom activity types

> Returns custom activity type definitions for a workspace. Filter by workspace using the \`where\` parameter: \`{"workspaceId": "\<WORKSPACE\_UUID>"}\`.\
> \
> Each workspace comes with default types (Call, Meeting). Use this endpoint to discover available types and their custom fields before creating activities.<br>

````json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.5.0"},"tags":[{"name":"Custom Activity Types","description":"Manage activity type definitions for a workspace. Each workspace comes with default types (Call, Meeting) and supports creating additional custom types.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)."}},"parameters":{"fields":{"name":"fields","in":"query","description":"Comma-separated list of fields to return. Defaults to all fields.","schema":{"type":"string"}},"where":{"name":"where","in":"query","description":"JSON-encoded filter object. All top-level conditions are combined with AND logic. Use `$or` for OR logic.\n\nThe available operators depend on the **data type** of the field you are filtering on.\n\n---\n\n## String fields\nFields like `name`, `domain`, `description`, `linkedin`, `source`, `externalId`, `location`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"name\": \"Linear\"}` |\n| `$eq` | Explicit exact match | `{\"name\": {\"$eq\": \"Linear\"}}` |\n| `$not` | Not equal | `{\"source\": {\"$not\": \"import\"}}` |\n| `$in` | Matches any value in array | `{\"domain\": {\"$in\": [\"linear.app\", \"granola.so\"]}}` |\n| `$notIn` | Matches none of the values | `{\"source\": {\"$notIn\": [\"import\", \"api\"]}}` |\n| `$contains` | Case-insensitive word-boundary substring match | `{\"name\": {\"$contains\": \"YC\"}}` |\n| `$notContains` | Does not contain | `{\"name\": {\"$notContains\": \"Test\"}}` |\n| `$containsAny` | Contains any of the given strings | `{\"name\": {\"$containsAny\": [\"YC\", \"Techstars\"]}}` |\n| `$startsWith` | Starts with prefix | `{\"domain\": {\"$startsWith\": \"app.\"}}` |\n| `$endsWith` | Ends with suffix | `{\"email\": {\"$endsWith\": \"@zero.inc\"}}` |\n| `$exists` | Field is present and truthy | `{\"linkedin\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent, null, or empty | `{\"linkedin\": {\"$notExists\": true}}` |\n\n---\n\n## Number fields\nFields like `value`, `confidence`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"value\": 5000}` |\n| `$eq` | Explicit exact match | `{\"value\": {\"$eq\": 5000}}` |\n| `$not` | Not equal | `{\"value\": {\"$not\": 0}}` |\n| `$gt` | Greater than | `{\"value\": {\"$gt\": 10000}}` |\n| `$gte` | Greater than or equal | `{\"value\": {\"$gte\": 5000}}` |\n| `$lt` | Less than | `{\"value\": {\"$lt\": 10000}}` |\n| `$lte` | Less than or equal | `{\"value\": {\"$lte\": 50000}}` |\n| `$in` | Matches any value in array | `{\"confidence\": {\"$in\": [0.25, 0.5, 0.75]}}` |\n| `$notIn` | Matches none of the values | `{\"confidence\": {\"$notIn\": [0, 1]}}` |\n| `$exists` | Field is present and truthy | `{\"value\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent, null, or zero | `{\"value\": {\"$notExists\": true}}` |\n\nMultiple operators can be combined on one field:\n```json\n{\"value\": {\"$gte\": 5000, \"$lt\": 10000}}\n```\n\n---\n\n## Date fields\nFields like `closeDate`, `startDate`, `endDate`, `createdAt`, `updatedAt`.\n\nValues can be ISO 8601 strings (`\"2026-01-01\"`, `\"2026-01-01T00:00:00Z\"`) or **relative time macros**.\n\n**Relative time macros:** `+Nd` / `-Nd` (days), `+Nw` / `-Nw` (weeks), `+Nm` / `-Nm` (months), `+Ny` / `-Ny` (years), `+Nh` / `-Nh` (hours), `+Ns` / `-Ns` (seconds), `now()`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `$gte` | On or after | `{\"closeDate\": {\"$gte\": \"2026-01-01\"}}` |\n| `$lte` | On or before | `{\"closeDate\": {\"$lte\": \"2026-03-31\"}}` |\n| `$gt` | After | `{\"createdAt\": {\"$gt\": \"2026-01-01T00:00:00Z\"}}` |\n| `$lt` | Before | `{\"createdAt\": {\"$lt\": \"now()\"}}` |\n| `$date` | Exact date match (compares date portion only) | `{\"closeDate\": {\"$date\": \"2026-01-15\"}}` |\n| `$exists` | Field is present and truthy | `{\"closeDate\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent or null | `{\"closeDate\": {\"$notExists\": true}}` |\n\nDate range example:\n```json\n{\"closeDate\": {\"$gte\": \"2026-01-01\", \"$lte\": \"2026-03-31\"}}\n```\nRelative date example (closing in next 30 days):\n```json\n{\"closeDate\": {\"$gte\": \"now()\", \"$lte\": \"+30d\"}}\n```\n\n---\n\n## Array fields\nFields like `listIds`, `ownerIds`, `contactIds`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `$includes` | Array contains the given value (use this — bare exact match is not supported) | `{\"listIds\": {\"$includes\": \"<LIST_UUID>\"}}` |\n| `$notIncludes` | Array does not contain the given value | `{\"ownerIds\": {\"$notIncludes\": \"<USER_UUID>\"}}` |\n| `$overlaps` | Array contains at least one of the given values | `{\"ownerIds\": {\"$overlaps\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$notOverlaps` | Array contains none of the given values | `{\"listIds\": {\"$notOverlaps\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$all` | Array contains all of the given values | `{\"listIds\": {\"$all\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$length` | Filter by array length (supports nested operators) | `{\"contactIds\": {\"$length\": {\"$gte\": 2}}}` |\n| `$exists` | Field is present and non-empty | `{\"ownerIds\": {\"$exists\": true}}` |\n| `$notExists` | Field is absent or empty | `{\"ownerIds\": {\"$notExists\": true}}` |\n\n---\n\n## UUID / ID fields\nFields like `id`, `workspaceId`, `companyId`, `stage`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"stage\": \"<PIPELINE_STAGE_UUID>\"}` |\n| `$in` | Matches any value in array | `{\"stage\": {\"$in\": [\"<UUID_1>\", \"<UUID_2>\"]}}` |\n| `$notIn` | Matches none of the values | `{\"stage\": {\"$notIn\": [\"<UUID_1>\"]}}` |\n| `$not` | Not equal | `{\"stage\": {\"$not\": \"<UUID>\"}}` |\n\n---\n\n## Boolean fields\nFields like `archived`.\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| *(exact)* | Exact match | `{\"archived\": false}` |\n| `$not` | Not equal | `{\"archived\": {\"$not\": true}}` |\n\n---\n\n## Logical operators\nThese work across all data types.\n\n`$or` — matches if **any** sub-condition is true:\n```json\n{\n  \"workspaceId\": \"<WORKSPACE_UUID>\",\n  \"$or\": [\n    {\"ownerIds\": {\"$overlaps\": [\"<USER_UUID_1>\", \"<USER_UUID_2>\"]}},\n    {\"closeDate\": {\"$gte\": \"2026-01-01\"}}\n  ]\n}\n```\n\n`$and` — matches if **all** sub-conditions are true (useful when you need multiple conditions on the same field):\n```json\n{\n  \"$and\": [\n    {\"name\": {\"$contains\": \"Enterprise\"}},\n    {\"name\": {\"$notContains\": \"Test\"}}\n  ]\n}\n```\n\n---\n\n## Dot-notation (relation filtering)\nUse dot-syntax to filter records based on properties of related objects:\n```json\n{\"company.name\": \"Linear\"}\n{\"company.domain\": {\"$in\": [\"linear.app\", \"granola.so\"]}}\n{\"company.location.city\": \"San Francisco\"}\n{\"companyProfile.categories\": {\"$overlaps\": [\"Sales\", \"Marketing\"]}}\n```\nAll operators available for the target field's data type can be used with dot-notation.\n\n---\n\n## Custom property filtering\nCustom 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.\n\nFilter on custom properties using `custom.<COLUMN_ID>` with operators appropriate for the column's type.\n\n> **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.\n\n```json\n// Text custom property\n{\"custom.54e1ca7d-69c3-4b77-8266-8085b5834116\": {\"$contains\": \"enterprise\"}}\n\n// Select custom property (use the option key UUID)\n{\"custom.a1b2c3d4-e5f6-7890-abcd-ef1234567890\": \"3e839b5c-b311-4887-b2da-727d2d75cdd6\"}\n\n// Multi-select custom property (use option key UUIDs)\n{\"custom.b2c3d4e5-f6a7-8901-bcde-f12345678901\": {\"$overlaps\": [\"a1b1c1d1-e1f1-1111-aaaa-111111111111\", \"b2b2c2d2-e2f2-2222-bbbb-222222222222\"]}}\n\n// Currency/number custom property\n{\"custom.c3d4e5f6-a7b8-9012-cdef-123456789012\": {\"$gte\": 100000}}\n\n// Date custom property\n{\"custom.d4e5f6a7-b8c9-0123-defa-234567890123\": {\"$gte\": \"2026-01-01\"}}\n\n// Boolean custom property\n{\"custom.e5f6a7b8-c9d0-1234-efab-345678901234\": true}\n\n// Check if custom property has a value\n{\"custom.f6a7b8c9-d0e1-2345-fabc-456789012345\": {\"$exists\": true}}\n```\n\n---\n\n## Complex example\nAll top-level keys are ANDed together:\n```json\n{\n  \"name\": {\"$contains\": \"Zero\"},\n  \"location.city\": \"Helsinki\",\n  \"location.country\": {\"$in\": [\"United Kingdom\", \"Germany\", \"Sweden\"]},\n  \"value\": {\"$gte\": 10000},\n  \"closeDate\": {\"$gte\": \"2026-01-01\", \"$lte\": \"2026-03-31\"},\n  \"ownerIds\": {\"$includes\": \"<USER_UUID>\"},\n  \"stage\": {\"$in\": [\"<UUID_1>\", \"<UUID_2>\"]},\n  \"lastActivity\": {\"$exists\": true},\n  \"companyProfile.categories\": {\"$overlaps\": [\"Sales\", \"Marketing\"]},\n  \"custom.54e1ca7d-69c3-4b77-8266-8085b5834116\": {\"$contains\": \"enterprise\"}\n}\n```\n","schema":{"type":"string"}},"limit":{"name":"limit","in":"query","description":"Maximum number of records to return","schema":{"type":"integer","default":100}},"offset":{"name":"offset","in":"query","description":"Pagination offset","schema":{"type":"integer","default":0}},"orderBy":{"name":"orderBy","in":"query","description":"JSON string for sort order","schema":{"type":"string"}}},"schemas":{"CustomActivityType":{"type":"object","description":"A definition for a type of activity that can be logged in a workspace (e.g. Call, Meeting, Site Visit).\n\nEach type can define custom fields that appear when logging an activity. Default types (Call, Meeting) are created automatically for new workspaces.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Display name of the activity type (e.g. \"Call\", \"Meeting\")"},"icon":{"type":"string","nullable":true,"description":"Icon identifier (e.g. \"phone\", \"calendar\", \"building\")"},"color":{"type":"string","nullable":true,"description":"Hex color code for UI display (e.g. \"#C48E1C\")"},"shortcut":{"type":"string","nullable":true,"description":"Keyboard shortcut key for quick activity logging (e.g. \"K\" for Call, \"M\" for Meeting)"},"description":{"type":"string","nullable":true,"description":"Human-readable description of the activity type"},"customFields":{"type":"array","description":"Custom field definitions for this activity type. When creating an activity with this type, the `custom` object on the activity can contain values keyed by these field IDs.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the custom field. Used as the key in the activity's `custom` object."},"name":{"type":"string","description":"Human-readable field name"},"type":{"type":"string","description":"Field type (e.g. \"select\", \"text\", \"number\")"},"options":{"type":"array","description":"Available options for select-type fields","items":{"type":"object","properties":{"key":{"type":"string","description":"The value stored on the activity"},"name":{"type":"string","description":"Human-readable option name"},"color":{"type":"string","description":"Hex color code for UI display"}}}}}}},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/customActivityTypes":{"get":{"tags":["Custom Activity Types"],"summary":"List custom activity types","description":"Returns custom activity type definitions for a workspace. Filter by workspace using the `where` parameter: `{\"workspaceId\": \"<WORKSPACE_UUID>\"}`.\n\nEach workspace comes with default types (Call, Meeting). Use this endpoint to discover available types and their custom fields before creating activities.\n","operationId":"listCustomActivityTypes","parameters":[{"$ref":"#/components/parameters/fields"},{"$ref":"#/components/parameters/where"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"$ref":"#/components/parameters/orderBy"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomActivityType"}},"total":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
````

## Create a custom activity type

> Create a new activity type definition in a workspace. Activity types define the categories of activities users can log (e.g. Call, Meeting, Site Visit).\
> \
> Each type can have custom fields that appear when logging an activity of that type.<br>

```json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.5.0"},"tags":[{"name":"Custom Activity Types","description":"Manage activity type definitions for a workspace. Each workspace comes with default types (Call, Meeting) and supports creating additional custom types.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)."}},"schemas":{"CustomActivityTypeCreate":{"type":"object","required":["workspaceId","name"],"properties":{"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Display name of the activity type"},"icon":{"type":"string","description":"Icon identifier"},"color":{"type":"string","description":"Hex color code"},"shortcut":{"type":"string","description":"Keyboard shortcut key"},"description":{"type":"string"},"customFields":{"type":"array","description":"Custom field definitions for this activity type","items":{"type":"object","required":["id","name","type"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"}}}}}}}}},"CustomActivityType":{"type":"object","description":"A definition for a type of activity that can be logged in a workspace (e.g. Call, Meeting, Site Visit).\n\nEach type can define custom fields that appear when logging an activity. Default types (Call, Meeting) are created automatically for new workspaces.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Display name of the activity type (e.g. \"Call\", \"Meeting\")"},"icon":{"type":"string","nullable":true,"description":"Icon identifier (e.g. \"phone\", \"calendar\", \"building\")"},"color":{"type":"string","nullable":true,"description":"Hex color code for UI display (e.g. \"#C48E1C\")"},"shortcut":{"type":"string","nullable":true,"description":"Keyboard shortcut key for quick activity logging (e.g. \"K\" for Call, \"M\" for Meeting)"},"description":{"type":"string","nullable":true,"description":"Human-readable description of the activity type"},"customFields":{"type":"array","description":"Custom field definitions for this activity type. When creating an activity with this type, the `custom` object on the activity can contain values keyed by these field IDs.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the custom field. Used as the key in the activity's `custom` object."},"name":{"type":"string","description":"Human-readable field name"},"type":{"type":"string","description":"Field type (e.g. \"select\", \"text\", \"number\")"},"options":{"type":"array","description":"Available options for select-type fields","items":{"type":"object","properties":{"key":{"type":"string","description":"The value stored on the activity"},"name":{"type":"string","description":"Human-readable option name"},"color":{"type":"string","description":"Hex color code for UI display"}}}}}}},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/customActivityTypes":{"post":{"tags":["Custom Activity Types"],"summary":"Create a custom activity type","description":"Create a new activity type definition in a workspace. Activity types define the categories of activities users can log (e.g. Call, Meeting, Site Visit).\n\nEach type can have custom fields that appear when logging an activity of that type.\n","operationId":"createCustomActivityType","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActivityTypeCreate"}}}},"responses":{"200":{"description":"Custom activity type created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CustomActivityType"},"sideEffects":{"type":"array","items":{}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
```

## Get a custom activity type

> Returns a single custom activity type by ID.\
> \
> If the type does not exist, the API returns HTTP 200 with an empty body (\`{}\`).<br>

```json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.5.0"},"tags":[{"name":"Custom Activity Types","description":"Manage activity type definitions for a workspace. Each workspace comes with default types (Call, Meeting) and supports creating additional custom types.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)."}},"schemas":{"CustomActivityType":{"type":"object","description":"A definition for a type of activity that can be logged in a workspace (e.g. Call, Meeting, Site Visit).\n\nEach type can define custom fields that appear when logging an activity. Default types (Call, Meeting) are created automatically for new workspaces.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Display name of the activity type (e.g. \"Call\", \"Meeting\")"},"icon":{"type":"string","nullable":true,"description":"Icon identifier (e.g. \"phone\", \"calendar\", \"building\")"},"color":{"type":"string","nullable":true,"description":"Hex color code for UI display (e.g. \"#C48E1C\")"},"shortcut":{"type":"string","nullable":true,"description":"Keyboard shortcut key for quick activity logging (e.g. \"K\" for Call, \"M\" for Meeting)"},"description":{"type":"string","nullable":true,"description":"Human-readable description of the activity type"},"customFields":{"type":"array","description":"Custom field definitions for this activity type. When creating an activity with this type, the `custom` object on the activity can contain values keyed by these field IDs.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the custom field. Used as the key in the activity's `custom` object."},"name":{"type":"string","description":"Human-readable field name"},"type":{"type":"string","description":"Field type (e.g. \"select\", \"text\", \"number\")"},"options":{"type":"array","description":"Available options for select-type fields","items":{"type":"object","properties":{"key":{"type":"string","description":"The value stored on the activity"},"name":{"type":"string","description":"Human-readable option name"},"color":{"type":"string","description":"Hex color code for UI display"}}}}}}},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/customActivityTypes/{customActivityTypeId}":{"get":{"tags":["Custom Activity Types"],"summary":"Get a custom activity type","description":"Returns a single custom activity type by ID.\n\nIf the type does not exist, the API returns HTTP 200 with an empty body (`{}`).\n","operationId":"getCustomActivityType","parameters":[{"name":"customActivityTypeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CustomActivityType"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
```

## Delete a custom activity type

> Delete a custom activity type. Use \`archive=true\` for soft delete.

```json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.5.0"},"tags":[{"name":"Custom Activity Types","description":"Manage activity type definitions for a workspace. Each workspace comes with default types (Call, Meeting) and supports creating additional custom types.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)."}},"schemas":{"CustomActivityType":{"type":"object","description":"A definition for a type of activity that can be logged in a workspace (e.g. Call, Meeting, Site Visit).\n\nEach type can define custom fields that appear when logging an activity. Default types (Call, Meeting) are created automatically for new workspaces.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Display name of the activity type (e.g. \"Call\", \"Meeting\")"},"icon":{"type":"string","nullable":true,"description":"Icon identifier (e.g. \"phone\", \"calendar\", \"building\")"},"color":{"type":"string","nullable":true,"description":"Hex color code for UI display (e.g. \"#C48E1C\")"},"shortcut":{"type":"string","nullable":true,"description":"Keyboard shortcut key for quick activity logging (e.g. \"K\" for Call, \"M\" for Meeting)"},"description":{"type":"string","nullable":true,"description":"Human-readable description of the activity type"},"customFields":{"type":"array","description":"Custom field definitions for this activity type. When creating an activity with this type, the `custom` object on the activity can contain values keyed by these field IDs.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the custom field. Used as the key in the activity's `custom` object."},"name":{"type":"string","description":"Human-readable field name"},"type":{"type":"string","description":"Field type (e.g. \"select\", \"text\", \"number\")"},"options":{"type":"array","description":"Available options for select-type fields","items":{"type":"object","properties":{"key":{"type":"string","description":"The value stored on the activity"},"name":{"type":"string","description":"Human-readable option name"},"color":{"type":"string","description":"Hex color code for UI display"}}}}}}},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"NotFound":{"description":"The requested resource was not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/customActivityTypes/{customActivityTypeId}":{"delete":{"tags":["Custom Activity Types"],"summary":"Delete a custom activity type","description":"Delete a custom activity type. Use `archive=true` for soft delete.","operationId":"deleteCustomActivityType","parameters":[{"name":"customActivityTypeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"archive","in":"query","description":"If true, soft deletes (archives) the type instead of permanently deleting it.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Custom activity type deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"Hard delete (`archive` omitted or `false`): returns `1` on success.\nSoft delete (`archive=true`): returns a single-element array containing the archived type object.\n","oneOf":[{"type":"integer"},{"type":"array","items":{"$ref":"#/components/schemas/CustomActivityType"}}]},"sideEffects":{"type":"array","items":{}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Update a custom activity type

> Update an existing custom activity type.\
> \
> \> \*\*⚠️ Important:\*\* The \`customFields\` array is \*\*replaced\*\* entirely on update, not merged. Always include all desired custom fields when patching.<br>

```json
{"openapi":"3.0.3","info":{"title":"Zero API","version":"1.5.0"},"tags":[{"name":"Custom Activity Types","description":"Manage activity type definitions for a workspace. Each workspace comes with default types (Call, Meeting) and supports creating additional custom types.\n"}],"servers":[{"url":"https://api.zero.inc","description":"Production server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"All API requests require a Bearer token in the Authorization header. Create an API key from [Workspace Settings → API keys](https://app.zero.inc/settings/workspace/api)."}},"schemas":{"CustomActivityTypeUpdate":{"type":"object","description":"All fields are optional. The `customFields` array replaces the existing array entirely on update — always include all desired fields.\n","properties":{"name":{"type":"string"},"icon":{"type":"string"},"color":{"type":"string"},"shortcut":{"type":"string"},"description":{"type":"string"},"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"}}}}}}}}},"CustomActivityType":{"type":"object","description":"A definition for a type of activity that can be logged in a workspace (e.g. Call, Meeting, Site Visit).\n\nEach type can define custom fields that appear when logging an activity. Default types (Call, Meeting) are created automatically for new workspaces.\n","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string","description":"Display name of the activity type (e.g. \"Call\", \"Meeting\")"},"icon":{"type":"string","nullable":true,"description":"Icon identifier (e.g. \"phone\", \"calendar\", \"building\")"},"color":{"type":"string","nullable":true,"description":"Hex color code for UI display (e.g. \"#C48E1C\")"},"shortcut":{"type":"string","nullable":true,"description":"Keyboard shortcut key for quick activity logging (e.g. \"K\" for Call, \"M\" for Meeting)"},"description":{"type":"string","nullable":true,"description":"Human-readable description of the activity type"},"customFields":{"type":"array","description":"Custom field definitions for this activity type. When creating an activity with this type, the `custom` object on the activity can contain values keyed by these field IDs.\n","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the custom field. Used as the key in the activity's `custom` object."},"name":{"type":"string","description":"Human-readable field name"},"type":{"type":"string","description":"Field type (e.g. \"select\", \"text\", \"number\")"},"options":{"type":"array","description":"Available options for select-type fields","items":{"type":"object","properties":{"key":{"type":"string","description":"The value stored on the activity"},"name":{"type":"string","description":"Human-readable option name"},"color":{"type":"string","description":"Hex color code for UI display"}}}}}}},"archived":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"createdById":{"type":"string","format":"uuid","nullable":true}}}},"responses":{"Unauthorized":{"description":"Authentication failed or token is invalid/expired","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"paths":{"/api/customActivityTypes/{customActivityTypeId}":{"patch":{"tags":["Custom Activity Types"],"summary":"Update a custom activity type","description":"Update an existing custom activity type.\n\n> **⚠️ Important:** The `customFields` array is **replaced** entirely on update, not merged. Always include all desired custom fields when patching.\n","operationId":"updateCustomActivityType","parameters":[{"name":"customActivityTypeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActivityTypeUpdate"}}}},"responses":{"200":{"description":"Custom activity type updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CustomActivityType"},"sideEffects":{"type":"array","items":{}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zero.inc/features/api/custom-activity-types.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
