> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nedzo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a contact view

> Save a contact filter as a view. A view is the audience of a campaign.

Every plan can use this endpoint. A view is the same saved filter the Contacts page uses, so it shows up in the dashboard too.

A view made with an API key shows the account owner as its creator. If the account has no owner, creating a view returns a `409`.

## Body

**workspaceId** `string` *required*

The workspace. Required.

**name** `string` *required*

The view name, 1 to 100 characters after trimming.

**filters** `object[]` (default: \[])

Up to 50 filters. See [Filters](#filters).

**sort** `object`

How the view sorts contacts: `{ "key", "direction" }`, where `direction` is `asc` or `desc`. Send `null` or leave it out for the default order.

## Filters

Each filter is `{ "id", "fieldKey", "operator", "value" }`, the same shape the Contacts page saves. Every filter is checked when you save the view: an unknown `fieldKey`, an operator the field doesn't support, or a missing or badly formatted value gets a `400` that lists each problem. That matters because a view is a campaign's audience, and a filter that doesn't apply would match every contact.

| fieldKey | Type | Operators |
| - | - | - |
| `name`, `email`, `phone`, `company` | text | `contains`, `not_contains`, `equals`, `not_equals`, `is_empty`, `is_not_empty` |
| `tags` | tags (comma-separated names) | `all_of`, `none_of`, `is_empty`, `is_not_empty` |
| `dnd` | yes/no | `equals`, `not_equals` |
| `createdAt`, `lastActivity` | date | `equals`, `not_equals`, `is_greater`, `is_less`, `is_between`, `in_past_days`, `is_empty`, `is_not_empty` |
| `custom:{{FieldName}}` | the custom field's type | the operators for that type; number fields: `equals`, `not_equals`, `is_greater`, `is_less`, `is_empty`, `is_not_empty` |

Values by type:

* **Yes/no** (`dnd` and yes/no custom fields): `Yes` or `No`. `true` and `false` also work, in any case. The view stores `Yes` or `No`, the same as the dashboard, so reading a view back shows `Yes` or `No`. `{ "fieldKey": "dnd", "operator": "equals", "value": "Yes" }` matches contacts on Do Not Disturb.
* **Date**: a day as `YYYY-MM-DD`, for example `2026-01-31`. `is_between` takes two days joined by `..`, start first: `2026-01-01..2026-01-31`. Both days count. `in_past_days` takes a whole number of days, for example `30`.
* **Number**: a number, for example `10` or `-2.5`.
* `is_empty` and `is_not_empty` need no value.

For a custom field, `FieldName` is its name with the spaces removed, for example `custom:{{LeadSource}}` for **Lead Source**. `value` is at most 1,000 characters and `id` at most 64.

```bash cURL theme={null}
curl -X POST "https://api.nedzo.ai/v1/contacts/views" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "789e4567-e89b-12d3-a456-426614174000",
    "name": "VIP leads",
    "filters": [{ "id": "flt_1", "fieldKey": "tags", "operator": "all_of", "value": "vip" }],
    "sort": { "key": "created_at", "direction": "desc" }
  }'
```

```json 201 Created theme={null}
{
  "id": "4d3c2b1a-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "workspaceId": "789e4567-e89b-12d3-a456-426614174000",
  "name": "VIP leads",
  "filters": [{ "id": "flt_1", "fieldKey": "tags", "operator": "all_of", "value": "vip" }],
  "sort": { "key": "created_at", "direction": "desc" },
  "creatorName": null,
  "createdAt": "2026-10-11T12:00:00Z",
  "updatedAt": "2026-10-11T12:00:00Z"
}
```

`creatorName` is `null` here. [List contact views](https://docs.nedzo.ai/api-reference/contacts/views/list.md) shows the creator's name.

## Errors

| Status | When |
| - | - |
| `400` | `name` is missing, empty or longer than 100 characters, there are more than 50 filters, a filter breaks a rule in [Filters](#filters), `sort` is not `{ "key", "direction" }` or `null`, `workspaceId` is not a UUID, or `workspaceId` is missing. |
| `404` | The workspace is not in this key's scope. |
| `409` | The request used an API key and the account has no owner to record the view under. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.