# API Reference

## Overview

The Knock API enables you to add a complete notification engine to your product. This API provides
programmatic access to integrating Knock via a REST-ful API.

```bash title="Base URL"
https://api.knock.app/v1
```

## Client libraries

Knock offers native SDKs in several popular programming languages:

<ul>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        Node.js
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        Python
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        Ruby
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        Go
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        PHP
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        Java
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        C# (dotnet)
      
    }
  </Text>
  <Text as="li" size="2" ml="4" data-tgph-list-item>
    {
      
        Elixir
      
    }
  </Text>
</ul>

## OpenAPI

Knock publishes an [OpenAPI](https://spec.openapis.org/oas/latest.html) document for the API. Use it to generate clients, import the API into tools like Postman or Insomnia, or inspect request and response schemas.

The OpenAPI specification is available in both JSON and YAML formats:

- [/openapi.json](https://docs.knock.app/openapi.json) — JSON format
- [/openapi.yaml](https://docs.knock.app/openapi.yaml) — YAML format

```bash title="OpenAPI document (JSON)"
https://docs.knock.app/openapi.json
```

```bash title="OpenAPI document (YAML)"
https://docs.knock.app/openapi.yaml
```

## API keys

Knock authenticates your API requests using your account's API keys. API requests made without authentication or using an incorrect key will return a 401 error. Requests using a valid key but with insufficient permissions will return a 403 error.

You can view and manage your API keys in the dashboard. You can create any number of API keys per environment, and there are two types of keys:

- Public keys are only meant to identify your account with Knock. They aren't secret, and can safely be made public in any of your client-side code. Publishable keys are prefixed with `pk_*`.

- Secret keys can perform any API request to Knock and should be kept secure and private. Be sure to prevent secret keys from being made publicly accessible, such as in client-side code, GitHub, unsecured S3 buckets, and so forth. Secret keys are prefixed with `sk_*`.

Each environment in your account can have any number of publishable and secret keys. API requests will be scoped to the provided key's environment. You can create and revoke keys at any time from the [API keys page](/developer-tools/api-keys) in your dashboard.

## Authentication

You must pass your API key to Knock as a Bearer token using the `Authorization` header.

```bash title="Authentication header"
Authorization: Bearer sk_test_12345
```

## Rate limits

Each endpoint in the Knock API is rate limited. Knock uses a tier system to determine the rate limit scale for each endpoint. When your request has been rate limited, the Knock API will return a `429 Too Many Requests` error in response.

> **Rate limit tiers are assigned per-endpoint.** 

Knock's default behavior scopes rate limits based on the authorizing credential used in your requests. When you use a public or private API key to authorize a request, Knock will scope the rate limit for each endpoint by the [environment](/concepts/environments) associated with the key. If you use a signed user token as your authorizing credential, Knock will scope the rate limit by both the key's environment and the signing user. See our documentation on [enhanced security mode](/in-app-ui/security-and-authentication#authentication-with-enhanced-security) for more details on working with signed user tokens.

If you're concerned about exceeding a Knock rate limit, please contact us and we can help figure out a usage rate that's right for your specific needs.

, "1 request / second"],
    [, "5 requests / second"],
    [, "60 requests / second"],
    [, "200 requests / second"],
    [, "1,000 requests / second"],
  ]}
/>

## Batch rate limits

Knock's batch and bulk endpoints may also have an additional layer of rate limiting applied. For these cases, Knock will also limit the number of times you can update a specific entity over a given scale. These limits are in place to prevent too many duplicate modifications applied to the same set of entities.

When you exceed a batch deduplication rate limit, Knock will still return a success (`2xx`) response if it is able to handle the request. For any entities not updated due to a rate limit hit, Knock will return the data as it exists at request time. Knock will also include an `x-ratelimited-{param}` header. The `{param}` value will be the name of the request param within which the rate limit was applied. The value will be a comma-delimited string of the param values that were rejected due to a rate limit hit.

Knock can apply batch deduplication rate limits to all or part of a request. If Knock rejects a subset of your batch, you can expect to see the full set of requested entities in the response body, and the IDs of those that were rejected in the `x-ratelimited-{param}` header.

, "1 update / second / entity"]]}
/>

```json title="Example request body"
{
  "message_ids": [1, 2, 3, 4]
}
```

```json title="Example response body"
[
  { "__typename": "Message", "id": 1 },
  { "__typename": "Message", "id": 2 },
  { "__typename": "Message", "id": 3 },
  { "__typename": "Message", "id": 4 }
]
```

```json title="Example response header"
{
  "x-ratelimited-message_ids": "2,4"
}
```

## Idempotent requests

Knock supports idempotency so that requests can be retried safely without unintended side effects.

To perform an idempotent request, set an `Idempotency-Key` header on your request. This idempotency key is a unique string of up to 255 characters that you generate for each request. It is used to identify and prevent the duplicate processing of requests. If you retry a request with the same idempotency key within 24 hours from the original request, Knock will return the same response as the original request. Idempotent requests are expected to be identical. To prevent accidental misuse, Knock returns an error when incoming parameters don't match those from the original request.

Idempotency is currently supported on a limited set of endpoints. Today, only `POST /workflows/:key/trigger` accepts the `Idempotency-Key` header; sending it on any other endpoint has no effect.

Idempotency keys can be random UUIDs, or they can have some meaning in your application. For example, if you are sending a notification after a user has placed an order, you could use a key that is a combination of the reason for the notification, the user ID, and the order ID (e.g. `order-placed:user-123:order-456`). If your user then cancels the order, you could use an idempotency key like `order-cancelled:user-123:order-456`. This will ensure each type of notification is only sent once, even if your system retries the request multiple times.

If you are making calls to Knock from a job queue, the ID of the job can be a good choice for an idempotency key. If the job fails and is retried, the same idempotency key will be used.

When a request is replayed from the idempotency cache, the response includes two headers:

1. An `original-x-request-id` header pointing to the `x-request-id` of the original request.
2. An `idempotent-replayed: true` header so you can tell the response was cached.

Knock only caches successful responses (`2xx`). Requests that return a `4xx` or `5xx` response are not stored, so retrying with the same idempotency key after a failure will execute the request again rather than replaying the previous response.

> **The default idempotency window for the Knock API is 24 hours.** support@knock.app.

```text title="Response headers (on cache hit)"
original-x-request-id: F1FIj5XwD_m4h0sAASfi
idempotent-replayed: true
```

## Data retention

Several V1 API endpoints return data that is subject to deletion according to the data retention policy associated with your account. These endpoints are tagged with the `Retention policy applied` badge.

For more information, see the [data retention docs](/manage-your-account/data-retention).

## Bulk endpoints

Knock exposes several endpoints that enqueue and return a `BulkOperation`. These endpoints perform their logic asynchronously, and you use the `BulkOperation` record to track progress.

In some cases, a bulk endpoint will accept a large set of entities to perform some action upon. In others, a bulk endpoint will accept a set of filter parameters and then execute an action across a large set of data on your account.

See the [Bulk operations section](/api-reference/bulk_operations) for more information on parsing and polling bulk operation statuses.

### Available bulk endpoints

The following bulk endpoints are available in the Knock API:

**Users**

- [Bulk identify users](/api-reference/users/bulk/identify)
- [Bulk set preferences](/api-reference/users/bulk/set_preferences)
- [Bulk delete users](/api-reference/users/bulk/delete)

**Objects**

- [Bulk set objects](/api-reference/objects/bulk/set)
- [Bulk add subscriptions](/api-reference/objects/bulk/add_subscriptions)
- [Bulk delete objects](/api-reference/objects/bulk/delete)
- [Bulk delete subscriptions](/api-reference/objects/bulk/delete_subscriptions)

**Tenants**

- [Bulk set tenants](/api-reference/tenants/bulk/set)
- [Bulk delete tenants](/api-reference/tenants/bulk/delete)

**Schedules**

- [Create schedules in bulk](/api-reference/schedules/bulk/create)

**Messages**

- [Bulk update message statuses for channel](/api-reference/channels/bulk/update_message_status)

## Trigger data filtering

Some V1 API endpoints that return lists of message data accept a `trigger_data` parameter. Knock uses this parameter to scope results it returns down to messages generated with the trigger data you provide.

The trigger data that Knock filters against is the _**combined and truncated data from the time the message was generated**_.

If a batch step preceded the creation of your message, the trigger data available for filtering will be the combined data for all the workflow triggers bundled into your batch. If a fetch step preceded, then the filterable data will include any data pulled in via the fetch step request.

Knock truncates trigger data for filtering to ensure it can efficiently process your request. The current data truncation rules are:

- Nested data structures (objects and arrays) are removed. Trigger data for filtering will be a JSON object with a single level of key-value pairs.
- Supported values are the JSON scalars string, number, boolean, and `null`.
- String values are limited to 256 characters in length. Strings that exceed this limit are truncated to the maximum.

## Pagination

All top-level API resources expose support for bulk fetches via a `list` method. For instance, you can [list users](#list-users), [list objects](#list-objects) in a collection, and [list subscriptions](#list-subscriptions).

Resources that return multiple entities support the same cursor-based pagination to interact with the resources, using `after`, `before`, and `page_size` parameters as well as returning a common format for the metadata associated with the page.

### Query parameters

- **after** (string): The pagination cursor to fetch items after. Usually derived from the after cursor in `PageInfo`.
- **before** (string): The pagination cursor to fetch items before. Usually derived from the before cursor in `PageInfo`.
- **page_size** (number (optional)): A number between 1 and 50 that represents the number of items to return in the response. Defaults to 50.

### Response format

- **entries** (object[]): A list of items contained in this response.
- **page_info** (PageInfo): Metadata about the page of data returned.

### PageInfo response details

- **after** (string): The cursor to use to fetch items after the last item in the list. May be null when there are no other items to retrieve.
- **before** (string): The cursor to use to fetch items before the first item in the list. May be null when there are no other items to retrieve.
- **page_size** (number): The maximum number of items requested in the page.
- **total_count** (number): The total number of items in this resource (up-to 10,000).

```json title="Response"
{
  "entries": [
    {
      "__typename": "User",
      "id": "user_1",
      "name": "User name",
      "email": "user-1@example.com",
      "created_at": null,
      "updated_at": "2021-03-05T12:00:00Z"
    },
    {
      "__typename": "User",
      "id": "user_2",
      "name": "User name",
      "email": "user-2@example.com",
      "created_at": null,
      "updated_at": "2021-03-05T12:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "page_size": 50,
    "total_count": 2,
    "after": null,
    "before": null
  }
}
```

## Errors

Knock uses standard HTTP response codes to indicate the success or failure of your API requests.

- `2xx` success status codes confirm that your request worked as expected.

- `4xx` error status codes indicate an error caused by incorrect or missing request information (e.g. providing an incorrect API key).

- `5xx` error status codes indicate a Knock server error.

For failed requests, the Knock API returns an `application/json` response with the following shared error structure:

```json title="Example error response"
{
  "code": "api_key_missing",
  "message": "No valid API key provided",
  "status": 401,
  "type": "authentication_error"
}
```

Branch on `code` to handle an error in your application, and use `type` to group codes into a category. The `message` may change to improve its explanation, so don't match on it. See [error codes](/api-reference/overview/error-codes) for the codes you're most likely to encounter and how to resolve each one.

A request to a path the API does not route returns JSON in a different shape, `{ "errors": { "detail": "404 Not Found" } }`. Check that the path matches an endpoint in this reference.

## Common error codes

Here's a list of common `4xx` error codes you may encounter while working with the Knock API. We also provide additional context on how to resolve them.

## Workflows

A [Workflow](/concepts/workflows) orchestrates the delivery of messages to your end users. When you configure a workflow you'll determine which channels its messages should route to, what those messages should look like on each channel, as well as any [functions](/designing-workflows/overview#function-steps)—batch, throttle, delay—you want applied to the messages prior to delivery.

To send notifications, you’ll trigger your workflows. A workflow is triggered by a `trigger` call, typically when an event occurs in your product that you want your users to know about (e.g. a new comment.)

### Available endpoints

- **POST** `/v1/workflows/{key}/trigger` - Trigger workflow
- **POST** `/v1/workflows/{key}/cancel` - Cancel workflow

### Trigger workflow

Trigger a workflow (specified by the key) to run for the given recipients, using the parameters provided. Returns an identifier for the workflow run request. All workflow runs are executed asynchronously. This endpoint also handles [inline identifications](/managing-recipients/identifying-recipients#inline-identifying-recipients) for the `actor`, `recipient`, and `tenant` fields.

#### Endpoint

`POST /v1/workflows/{key}/trigger`

**Rate limit tier:** 5

#### Path parameters

- **key** (string) *required* - Key of the workflow to trigger.

#### Request body

A request to trigger a notification workflow.

##### Example

```json
{
  "actor": "mr_dna",
  "cancellation_key": "isla_nublar_incident_1993",
  "data": {
    "affected_areas": [
      "visitor_center",
      "raptor_pen",
      "trex_paddock"
    ],
    "attraction_id": "paddock_rex_01",
    "evacuation_protocol": "active",
    "message": "Life finds a way",
    "severity": "critical",
    "system_status": "fences_failing"
  },
  "recipients": [
    "dr_grant",
    "dr_sattler",
    "dr_malcolm"
  ],
  "settings": {
    "sandbox_mode": true,
    "skip_delay": true
  },
  "tenant": "ingen_isla_nublar"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "workflow_run_id": "123e4567-e89b-12d3-a456-426614174000"
}
```

### Cancel workflow

When invoked for a workflow using a specific workflow key and cancellation key, will cancel any queued workflow runs associated with that key/cancellation key pair. Can optionally be provided one or more recipients to scope the request to.

#### Endpoint

`POST /v1/workflows/{key}/cancel`

**Rate limit tier:** 5

#### Path parameters

- **key** (string) *required* - The key of the workflow to cancel.

#### Request body

When invoked using a specific workflow key and cancellation key, will cancel any queued workflow runs associated with that key/cancellation key pair. Can optionally provide one or more recipients to scope the request to.

##### Example

```json
{
  "cancellation_key": "cancel-workflow-123",
  "recipients": [
    "jhammond"
  ]
}
```

#### Responses

##### 204

No Content

## Workflow runs

A workflow run represents an individual execution of a [workflow](/concepts/workflows) for a specific recipient. Use the workflow runs API to inspect the status and event history of a workflow run, including which steps were executed and any errors encountered.

### Available endpoints

- **GET** `/v1/workflow_recipient_runs` - List workflow recipient runs
- **GET** `/v1/workflow_recipient_runs/{id}` - Get a workflow recipient run

### List workflow recipient runs

Returns a paginated list of workflow recipient runs for the current environment.

#### Endpoint

`GET /v1/workflow_recipient_runs`

**Rate limit tier:** 2

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).
- **workflow** (string) - Limits the results to workflow recipient runs for the given workflow key.
- **status** (array) - Limits the results to workflow recipient runs with the given status.
- **tenant** (string) - Limits the results to workflow recipient runs for the given tenant.
- **has_errors** (boolean) - Limits the results to workflow recipient runs that have errors.
- **recipient** (string) - Limits the results to workflow recipient runs for the given recipient. Accepts a user ID string or an object reference with `id` and `collection`.
- **starting_at** (string) - Limits the results to workflow recipient runs started after the given date.
- **ending_at** (string) - Limits the results to workflow recipient runs started before the given date.

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "WorkflowRecipientRun",
      "actor": "user_456",
      "error_count": 0,
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "inserted_at": "2025-01-01T00:00:00Z",
      "recipient": "user_123",
      "status": "completed",
      "tenant": "tenant_abc",
      "trigger_source": {
        "cancellation_key": "comment-123-user-456",
        "type": "api"
      },
      "updated_at": "2025-01-01T00:05:00Z",
      "workflow": "comment-created",
      "workflow_run_id": "660e8400-e29b-41d4-a716-446655440000"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Get a workflow recipient run

Returns a single workflow recipient run with its associated events.

#### Endpoint

`GET /v1/workflow_recipient_runs/{id}`

**Rate limit tier:** 2

#### Path parameters

- **id** (string) *required* - The unique identifier for the workflow recipient run (per-recipient).

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "WorkflowRecipientRun",
  "actor": "user_456",
  "error_count": 0,
  "events": [
    {
      "__typename": "WorkflowRecipientRunEvent",
      "attempt": 1,
      "data": {
        "channel_type": "email",
        "message_id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe"
      },
      "event": "message_enqueued",
      "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
      "inserted_at": "2025-01-01T00:00:00Z",
      "status": "ok",
      "step_ref": "email_step_1",
      "step_type": "channel"
    }
  ],
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "inserted_at": "2025-01-01T00:00:00Z",
  "recipient": "user_123",
  "status": "completed",
  "tenant": "tenant_abc",
  "trigger_source": {
    "cancellation_key": "comment-123-user-456",
    "type": "api"
  },
  "updated_at": "2025-01-01T00:05:00Z",
  "workflow": "comment-created",
  "workflow_run_id": "660e8400-e29b-41d4-a716-446655440000"
}
```

### WorkflowRecipientRun

A workflow recipient run represents an individual execution of a workflow for a specific recipient.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **actor** (unknown) - The actor who triggered the workflow recipient run.
- **error_count** (integer) - The number of errors encountered during the workflow recipient run.
- **id** (string) *required* - The unique identifier for the workflow recipient run (per-recipient).
- **inserted_at** (string) *required* - Timestamp when the resource was created.
- **recipient** (unknown) *required* - A reference to a recipient, either a user identifier (string) or an object reference (ID, collection).
- **status** (string) *required* - The current status of the workflow recipient run. One of `queued`, `processing`, `paused`, `completed`, or `cancelled`.
- **tenant** (string) - The tenant associated with the workflow recipient run.
- **trigger_source** (object) *required* - Describes how the workflow was triggered.
- **updated_at** (string) *required* - The timestamp when the resource was last updated.
- **workflow** (string) *required* - The key of the workflow that was executed.
- **workflow_run_id** (string) *required* - The identifier for the top-level workflow run shared across all recipients in a single trigger.

#### Example

```json
{
  "__typename": "WorkflowRecipientRun",
  "actor": "user_456",
  "error_count": 0,
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "inserted_at": "2025-01-01T00:00:00Z",
  "recipient": "user_123",
  "status": "completed",
  "tenant": "tenant_abc",
  "trigger_source": {
    "cancellation_key": "comment-123-user-456",
    "type": "api"
  },
  "updated_at": "2025-01-01T00:05:00Z",
  "workflow": "comment-created",
  "workflow_run_id": "660e8400-e29b-41d4-a716-446655440000"
}
```

### WorkflowRecipientRunDetail

A single workflow recipient run with its events.

#### Attributes

#### Example

```json
{
  "__typename": "WorkflowRecipientRun",
  "actor": "user_456",
  "error_count": 0,
  "events": [
    {
      "__typename": "WorkflowRecipientRunEvent",
      "attempt": 1,
      "data": {
        "channel_type": "email",
        "message_id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe"
      },
      "event": "message_enqueued",
      "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
      "inserted_at": "2025-01-01T00:00:00Z",
      "status": "ok",
      "step_ref": "email_step_1",
      "step_type": "channel"
    }
  ],
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "inserted_at": "2025-01-01T00:00:00Z",
  "recipient": "user_123",
  "status": "completed",
  "tenant": "tenant_abc",
  "trigger_source": {
    "cancellation_key": "comment-123-user-456",
    "type": "api"
  },
  "updated_at": "2025-01-01T00:05:00Z",
  "workflow": "comment-created",
  "workflow_run_id": "660e8400-e29b-41d4-a716-446655440000"
}
```

### WorkflowRecipientRunEvent

An event that occurred during a workflow recipient run.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **attempt** (integer) - The attempt number of the workflow recipient run event. Increments for each retry.
- **data** (object) - Event-specific data associated with the event.
- **event** (string) *required* - The type of event that occurred.
- **id** (string) *required* - The unique identifier for the event.
- **inserted_at** (string) *required* - Timestamp when the resource was created.
- **status** (string) *required* - Whether the event represents a successful or error state.
- **step_ref** (string) - The reference of the workflow step associated with this event.
- **step_type** (string) - The type of workflow step associated with this event.

#### Example

```json
{
  "__typename": "WorkflowRecipientRunEvent",
  "attempt": 1,
  "data": {
    "channel_type": "email",
    "message_id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe"
  },
  "event": "message_enqueued",
  "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
  "inserted_at": "2025-01-01T00:00:00Z",
  "status": "ok",
  "step_ref": "email_step_1",
  "step_type": "channel"
}
```

## Messages

A [Message](/concepts/messages) is a notification delivered on a particular channel to a user.

### Available endpoints

- **GET** `/v1/messages/{message_id}` - Get message
- **GET** `/v1/messages/{message_id}/content` - Get message content
- **GET** `/v1/messages` - List messages
- **GET** `/v1/messages/{message_id}/events` - List events
- **GET** `/v1/messages/{message_id}/delivery_logs` - List delivery logs
- **GET** `/v1/messages/{message_id}/activities` - List activities
- **PUT** `/v1/messages/{message_id}/seen` - Mark message as seen
- **DELETE** `/v1/messages/{message_id}/seen` - Mark message as unseen
- **PUT** `/v1/messages/{message_id}/read` - Mark message as read
- **DELETE** `/v1/messages/{message_id}/read` - Mark message as unread
- **PUT** `/v1/messages/{message_id}/interacted` - Mark message as interacted
- **PUT** `/v1/messages/{message_id}/archived` - Archive message
- **DELETE** `/v1/messages/{message_id}/archived` - Unarchive message

### Get message

Retrieves a specific message by its ID.

#### Endpoint

`GET /v1/messages/{message_id}`

**Rate limit tier:** 4

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "mr_arnold",
    "mr_muldoon"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "affected_areas": [
      "visitor_center",
      "raptor_pen",
      "trex_paddock"
    ],
    "attraction_id": "paddock_rex_01",
    "evacuation_protocol": "active",
    "message": "Life finds a way",
    "severity": "critical",
    "system_status": "fences_failing"
  },
  "engagement_statuses": [
    "read",
    "seen"
  ],
  "id": "2w3YUpTTOxuDvZFji8OMsKrG176",
  "inserted_at": "1993-06-11T21:15:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": "1993-06-11T21:30:00Z",
  "recipient": "dr_grant",
  "recipient_snapshot": {
    "email": "user@example.com",
    "name": "John Doe"
  },
  "scheduled_at": null,
  "seen_at": "1993-06-11T21:29:45Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "security",
      "emergency"
    ],
    "key": "security-breach-alert",
    "step_ref": "alert_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000",
    "workflow_recipient_run_id": "def01234-a56b-78c9-d012-345678901bcd",
    "workflow_run_id": "789e0123-f45a-67b8-c901-234567890abc"
  },
  "status": "sent",
  "tenant": "ingen_isla_nublar",
  "updated_at": "1993-06-11T21:30:05Z",
  "workflow": "security-breach-alert"
}
```

### Get message content

Returns the fully rendered contents of a message, where the response depends on which channel the message was sent through.

#### Endpoint

`GET /v1/messages/{message_id}/content`

**Rate limit tier:** 4

#### Path parameters

- **message_id** (string) *required* - The ID of the message to fetch contents of.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "MessageContent",
  "data": {
    "__typename": "MessageSmsContent",
    "body": "URGENT: Power failure detected in perimeter fencing. Backup generators failed to engage. Technical team dispatched. Maintain lockdown protocols.",
    "to": "+15553982647"
  },
  "inserted_at": "1993-06-11T20:30:00Z",
  "message_id": "2w3YUpTTOxuDvZFji8OMsKrG176"
}
```

### List messages

Returns a paginated list of messages for the current environment.

#### Endpoint

`GET /v1/messages`

**Rate limit tier:** 4

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).
- **tenant** (string) - Limits the results to items with the corresponding tenant.
- **channel_id** (string) - Limits the results to items with the corresponding channel ID.
- **status** (array) - Limits the results to messages with the given delivery status.
- **engagement_status** (array) - Limits the results to messages with the given engagement status.
- **message_ids** (array) - Limits the results to only the message IDs given (max 50). Note: when using this option, the results will be subject to any other filters applied to the query.
- **workflow_categories** (array) - Limits the results to messages related to any of the provided categories.
- **source** (string) - Limits the results to messages triggered by the given workflow key.
- **workflow_run_id** (string) - Limits the results to messages associated with the top-level workflow run ID returned by the workflow trigger request.
- **workflow_recipient_run_id** (string) - Limits the results to messages for a specific recipient's workflow run.
- **trigger_data** (string) - Limits the results to only messages that were generated with the given data. See [trigger data filtering](/api-reference/overview/trigger-data-filtering) for more information.
- **inserted_at.gt** (string) - Limits the results to items inserted after the given date.
- **inserted_at.gte** (string) - Limits the results to items inserted after or on the given date.
- **inserted_at.lt** (string) - Limits the results to items inserted before the given date.
- **inserted_at.lte** (string) - Limits the results to items inserted before or on the given date.

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "Message",
      "actors": [
        "mr_arnold",
        "mr_muldoon"
      ],
      "archived_at": null,
      "channel_id": "123e4567-e89b-12d3-a456-426614174000",
      "clicked_at": null,
      "data": {
        "affected_areas": [
          "visitor_center",
          "raptor_pen",
          "trex_paddock"
        ],
        "attraction_id": "paddock_rex_01",
        "evacuation_protocol": "active",
        "message": "Life finds a way",
        "severity": "critical",
        "system_status": "fences_failing"
      },
      "engagement_statuses": [
        "read",
        "seen"
      ],
      "id": "2w3YUpTTOxuDvZFji8OMsKrG176",
      "inserted_at": "1993-06-11T21:15:00Z",
      "interacted_at": null,
      "link_clicked_at": null,
      "metadata": {
        "external_id": "123e4567-e89b-12d3-a456-426614174000"
      },
      "read_at": "1993-06-11T21:30:00Z",
      "recipient": "dr_grant",
      "recipient_snapshot": {
        "email": "user@example.com",
        "name": "John Doe"
      },
      "scheduled_at": null,
      "seen_at": "1993-06-11T21:29:45Z",
      "source": {
        "__typename": "NotificationSource",
        "categories": [
          "security",
          "emergency"
        ],
        "key": "security-breach-alert",
        "step_ref": "alert_step_1",
        "version_id": "123e4567-e89b-12d3-a456-426614174000",
        "workflow_recipient_run_id": "def01234-a56b-78c9-d012-345678901bcd",
        "workflow_run_id": "789e0123-f45a-67b8-c901-234567890abc"
      },
      "status": "sent",
      "tenant": "ingen_isla_nublar",
      "updated_at": "1993-06-11T21:30:05Z",
      "workflow": "security-breach-alert"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List events

Returns a paginated list of events for the specified message.

#### Endpoint

`GET /v1/messages/{message_id}/events`

**Rate limit tier:** 3

#### Path parameters

- **message_id** (string) *required* - The ID of the message to fetch events for.

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "MessageEvent",
      "data": null,
      "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
      "inserted_at": "2021-01-01T00:00:00Z",
      "recipient": "user_123",
      "type": "message.sent"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List delivery logs

Returns a paginated list of delivery logs for the specified message.

#### Endpoint

`GET /v1/messages/{message_id}/delivery_logs`

**Rate limit tier:** 3

#### Path parameters

- **message_id** (string) *required* - The ID of the message to fetch delivery logs for.

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "MessageDeliveryLog",
      "environment_id": "123e4567-e89b-12d3-a456-426614174000",
      "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
      "inserted_at": "2021-01-01T00:00:00Z",
      "request": {
        "body": {
          "html_content": "<html></html>"
        },
        "headers": {
          "Content-Type": "application/json"
        },
        "host": "localhost",
        "method": "GET",
        "path": "/",
        "query": "?foo=bar"
      },
      "response": {
        "body": {
          "success": true
        },
        "headers": {
          "Content-Type": "application/json"
        },
        "status": 200
      },
      "service_name": "Postmark"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List activities

Returns a paginated list of activities for the specified message.

#### Endpoint

`GET /v1/messages/{message_id}/activities`

**Rate limit tier:** 4

#### Path parameters

- **message_id** (string) *required* - The ID of the message to fetch activities for.

#### Query parameters

- **trigger_data** (string) - The trigger data to filter activities by.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "Activity",
      "actor": null,
      "data": {
        "foo": "bar"
      },
      "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
      "inserted_at": "2024-01-01T00:00:00Z",
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Mark message as seen

Marks a message as `seen`. This indicates that the user has viewed the message in their feed or inbox. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`PUT /v1/messages/{message_id}/seen`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [
    "seen"
  ],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": null,
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": "2025-01-01T00:01:00Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Mark message as unseen

Marks a message as `unseen`. This reverses the `seen` state. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`DELETE /v1/messages/{message_id}/seen`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": null,
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": null,
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Mark message as read

Marks a message as `read`. This indicates that the user has read the message content. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`PUT /v1/messages/{message_id}/read`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [
    "seen",
    "read"
  ],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": "2025-01-01T00:02:00Z",
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": "2025-01-01T00:01:00Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Mark message as unread

Marks a message as `unread`. This reverses the `read` state. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`DELETE /v1/messages/{message_id}/read`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [
    "seen"
  ],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": null,
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": "2025-01-01T00:01:00Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Mark message as interacted

Marks a message as `interacted` with by the user. This can include any user action on the message, with optional metadata about the specific interaction. Cannot include more than 5 key-value pairs, must not contain nested data. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`PUT /v1/messages/{message_id}/interacted`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Request body

A request to mark a message as interacted with.

##### Example

```json
{
  "metadata": {
    "key": "value"
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [
    "seen",
    "interacted"
  ],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": "2025-01-01T00:03:00Z",
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": null,
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": "2025-01-01T00:01:00Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Archive message

Archives a message for the user. Archived messages are hidden from the default message list in the feed but can still be accessed and unarchived later.

#### Endpoint

`PUT /v1/messages/{message_id}/archived`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": "2025-01-01T00:04:00Z",
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [
    "seen",
    "archived"
  ],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": null,
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": "2025-01-01T00:01:00Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Unarchive message

Removes a message from the archived state, making it visible in the default message list in the feed again.

#### Endpoint

`DELETE /v1/messages/{message_id}/archived`

**Rate limit tier:** 2

#### Path parameters

- **message_id** (string) *required* - The unique identifier for the message.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Message",
  "actors": [
    "user_123"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "foo": "bar"
  },
  "engagement_statuses": [
    "seen"
  ],
  "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
  "inserted_at": "2021-01-01T00:00:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": null,
  "recipient": "user_123",
  "scheduled_at": null,
  "seen_at": "2025-01-01T00:01:00Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "collaboration"
    ],
    "key": "comment-created",
    "step_ref": "email_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "status": "sent",
  "tenant": "tenant_123",
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "comment-created"
}
```

### Batch operations

Operations that can be performed on a batch of messages.

#### Available endpoints

- **GET** `/v1/messages/batch/content` - Batch get message contents
- **POST** `/v1/messages/batch/seen` - Mark messages as seen
- **POST** `/v1/messages/batch/unseen` - Mark messages as unseen
- **POST** `/v1/messages/batch/read` - Mark messages as read
- **POST** `/v1/messages/batch/unread` - Mark messages as unread
- **POST** `/v1/messages/batch/interacted` - Mark messages as interacted
- **POST** `/v1/messages/batch/archived` - Mark messages as archived
- **POST** `/v1/messages/batch/unarchived` - Mark messages as unarchived

### Batch get message contents

Get the contents of multiple messages in a single request.

#### Endpoint

`GET /v1/messages/batch/content`

**Rate limit tier:** 4

#### Query parameters

- **message_ids** (array) *required* - The IDs of the messages to fetch contents of.

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "MessageContent",
    "data": {
      "__typename": "MessageSmsContent",
      "body": "URGENT: Power failure detected in perimeter fencing. Backup generators failed to engage. Technical team dispatched. Maintain lockdown protocols.",
      "to": "+15553982647"
    },
    "inserted_at": "1993-06-11T20:30:00Z",
    "message_id": "2w3YUpTTOxuDvZFji8OMsKrG176"
  }
]
```

### Mark messages as seen

Marks the given messages as `seen`. This indicates that the user has viewed the message in their feed or inbox. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`POST /v1/messages/batch/seen`

**Rate limit tier:** 3

#### Request body

Request to update the status of multiple messages in batch.

##### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": null,
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [
      "seen"
    ],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": null,
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": null,
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": "2025-01-01T00:01:00Z",
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### Mark messages as unseen

Marks the given messages as `unseen`. This reverses the `seen` state. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`POST /v1/messages/batch/unseen`

**Rate limit tier:** 3

#### Request body

Request to update the status of multiple messages in batch.

##### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": null,
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": null,
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": null,
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": null,
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### Mark messages as read

Marks the given messages as `read`. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`POST /v1/messages/batch/read`

**Rate limit tier:** 3

#### Request body

Request to update the status of multiple messages in batch.

##### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": null,
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [
      "seen",
      "read"
    ],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": null,
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": "2025-01-01T00:02:00Z",
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": "2025-01-01T00:01:00Z",
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### Mark messages as unread

Marks the given messages as `unread`. This reverses the `read` state. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`POST /v1/messages/batch/unread`

**Rate limit tier:** 3

#### Request body

Request to update the status of multiple messages in batch.

##### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": null,
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [
      "seen"
    ],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": null,
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": null,
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": "2025-01-01T00:01:00Z",
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### Mark messages as interacted

Marks the given messages as interacted with by the user. This can include any user action on the message, with optional metadata about the specific interaction. Cannot include more than 5 key-value pairs, must not contain nested data. Read more about message engagement statuses [here](/send-notifications/message-statuses#engagement-status).

#### Endpoint

`POST /v1/messages/batch/interacted`

**Rate limit tier:** 3

#### Request body

A request to batch mark messages as interacted with.

##### Example

```json
{
  "message_ids": [
    "1jNaXzB2RZX3LY8wVQnfCKyPnv7"
  ],
  "metadata": {
    "key": "value"
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": null,
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [
      "seen",
      "interacted"
    ],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": "2025-01-01T00:03:00Z",
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": null,
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": "2025-01-01T00:01:00Z",
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### Mark messages as archived

Marks the given messages as archived. Archived messages are hidden from the default message list in the feed but can still be accessed and unarchived later.

#### Endpoint

`POST /v1/messages/batch/archived`

**Rate limit tier:** 3

#### Request body

Request to update the status of multiple messages in batch.

##### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": "2025-01-01T00:04:00Z",
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [
      "seen",
      "archived"
    ],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": null,
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": null,
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": "2025-01-01T00:01:00Z",
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### Mark messages as unarchived

Marks the given messages as unarchived. This reverses the `archived` state. Archived messages are hidden from the default message list in the feed but can still be accessed and unarchived later.

#### Endpoint

`POST /v1/messages/batch/unarchived`

**Rate limit tier:** 3

#### Request body

Request to update the status of multiple messages in batch.

##### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Message",
    "actors": [
      "user_123"
    ],
    "archived_at": null,
    "channel_id": "123e4567-e89b-12d3-a456-426614174000",
    "clicked_at": null,
    "data": {
      "foo": "bar"
    },
    "engagement_statuses": [
      "seen"
    ],
    "id": "1jNaXzB2RZX3LY8wVQnfCKyPnv7",
    "inserted_at": "2021-01-01T00:00:00Z",
    "interacted_at": null,
    "link_clicked_at": null,
    "metadata": {
      "external_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "read_at": null,
    "recipient": "user_123",
    "scheduled_at": null,
    "seen_at": "2025-01-01T00:01:00Z",
    "source": {
      "__typename": "NotificationSource",
      "categories": [
        "collaboration"
      ],
      "key": "comment-created",
      "version_id": "123e4567-e89b-12d3-a456-426614174000"
    },
    "status": "sent",
    "tenant": "tenant_123",
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "comment-created"
  }
]
```

### BatchMessagesStatusRequest

Request to update the status of multiple messages in batch.

#### Attributes

- **message_ids** (array) *required* - The message IDs to update the status of.

#### Example

```json
{
  "message_ids": [
    "2w3YUpTTOxuDvZFji8OMsKrG176",
    "2w3YVRbPXMIh8Zq6oBFcVDA5xes"
  ]
}
```

### Message

Represents a single message that was generated by a workflow for a given channel.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **actors** (array) - One or more actors that are associated with this message. Note: this is a list that can contain up to 10 actors if the message is produced from a [batch](/designing-workflows/batch-function).
- **archived_at** (string) - Timestamp when the message was archived.
- **channel** (object) - A configured channel, which is a way to route messages to a provider.
- **channel_id** (string) *required* - Deprecated, use channel.id instead.
- **clicked_at** (string) - Timestamp when the message was clicked.
- **data** (object) - Data associated with the message’s workflow run. Includes the workflow trigger request’s `data` payload merged with any additional data returned by a [fetch function](/designing-workflows/fetch-function). For messages produced after a [batch step](/designing-workflows/batch-function), includes the payload `data` from the most-recent trigger request (the final `activity` in the batch).
- **engagement_statuses** (array) *required* - A list of engagement statuses.
- **id** (string) *required* - The unique identifier for the message.
- **inserted_at** (string) *required* - Timestamp when the resource was created.
- **interacted_at** (string) - Timestamp when the message was interacted with.
- **link_clicked_at** (string) - Timestamp when a link in the message was clicked.
- **metadata** (object) - The metadata associated with the message.
- **read_at** (string) - Timestamp when the message was read.
- **recipient** (unknown) *required* - A reference to a recipient, either a user identifier (string) or an object reference (ID, collection).
- **recipient_snapshot** (object) - The destination the message was delivered to, captured at send time. Email channels carry `email`/`name`; chat channels carry the destination `channel_id` or `user_id`, or `via_incoming_webhook`. Null when no snapshot was captured.
- **scheduled_at** (string) - Timestamp when the message was scheduled to be sent.
- **seen_at** (string) - Timestamp when the message was seen.
- **source** (object) *required* - The workflow or guide that triggered the message.
- **status** (string) *required* - The message delivery status.
- **tenant** (string) - The ID of the `tenant` associated with the message. Only present when a `tenant` is provided on a workflow trigger request.
- **updated_at** (string) *required* - The timestamp when the resource was last updated.
- **workflow** (string) - The key of the workflow that generated the message.

#### Example

```json
{
  "__typename": "Message",
  "actors": [
    "mr_arnold",
    "mr_muldoon"
  ],
  "archived_at": null,
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "clicked_at": null,
  "data": {
    "affected_areas": [
      "visitor_center",
      "raptor_pen",
      "trex_paddock"
    ],
    "attraction_id": "paddock_rex_01",
    "evacuation_protocol": "active",
    "message": "Life finds a way",
    "severity": "critical",
    "system_status": "fences_failing"
  },
  "engagement_statuses": [
    "read",
    "seen"
  ],
  "id": "2w3YUpTTOxuDvZFji8OMsKrG176",
  "inserted_at": "1993-06-11T21:15:00Z",
  "interacted_at": null,
  "link_clicked_at": null,
  "metadata": {
    "external_id": "123e4567-e89b-12d3-a456-426614174000"
  },
  "read_at": "1993-06-11T21:30:00Z",
  "recipient": "dr_grant",
  "recipient_snapshot": {
    "email": "user@example.com",
    "name": "John Doe"
  },
  "scheduled_at": null,
  "seen_at": "1993-06-11T21:29:45Z",
  "source": {
    "__typename": "NotificationSource",
    "categories": [
      "security",
      "emergency"
    ],
    "key": "security-breach-alert",
    "step_ref": "alert_step_1",
    "version_id": "123e4567-e89b-12d3-a456-426614174000",
    "workflow_recipient_run_id": "def01234-a56b-78c9-d012-345678901bcd",
    "workflow_run_id": "789e0123-f45a-67b8-c901-234567890abc"
  },
  "status": "sent",
  "tenant": "ingen_isla_nublar",
  "updated_at": "1993-06-11T21:30:05Z",
  "workflow": "security-breach-alert"
}
```

### Activity

An activity associated with a workflow trigger request. Messages produced after a [batch step](/designing-workflows/batch-function) can be associated with one or more activities. Non-batched messages will always be associated with a single activity.

#### Attributes

- **__typename** (string) - The typename of the schema.
- **actor** (object) - The actor who performed the activity.
- **data** (object) - The workflow trigger `data` payload associated with the activity.
- **id** (string) - Unique identifier for the activity.
- **inserted_at** (string) - Timestamp when the activity was created.
- **recipient** (object) - A recipient of a notification, which is either a user or an object.
- **updated_at** (string) - Timestamp when the activity was last updated.

#### Example

```json
{
  "__typename": "Activity",
  "actor": null,
  "data": {
    "foo": "bar"
  },
  "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
  "inserted_at": "2024-01-01T00:00:00Z",
  "recipient": {
    "__typename": "User",
    "avatar": null,
    "created_at": null,
    "email": "jane@ingen.net",
    "id": "jane",
    "name": "Jane Doe",
    "phone_number": null,
    "timezone": null,
    "updated_at": "2024-05-22T12:00:00Z"
  },
  "updated_at": "2024-01-01T00:00:00Z"
}
```

### MessageDeliveryLog

A message delivery log contains a `request` from Knock to a downstream provider and the `response` that was returned.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **environment_id** (string) *required* - The ID of the environment in which the message delivery occurred.
- **id** (string) *required* - The unique identifier for the message delivery log.
- **inserted_at** (string) *required* - Timestamp when the message delivery log was created.
- **request** (object) *required* - A message delivery log request.
- **response** (object) *required* - A message delivery log response.
- **service_name** (string) *required* - The name of the service that processed the delivery.

#### Example

```json
{
  "__typename": "MessageDeliveryLog",
  "environment_id": "123e4567-e89b-12d3-a456-426614174000",
  "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
  "inserted_at": "2021-01-01T00:00:00Z",
  "request": {
    "body": {
      "html_content": "<html></html>"
    },
    "headers": {
      "Content-Type": "application/json"
    },
    "host": "localhost",
    "method": "GET",
    "path": "/",
    "query": "?foo=bar"
  },
  "response": {
    "body": {
      "success": true
    },
    "headers": {
      "Content-Type": "application/json"
    },
    "status": 200
  },
  "service_name": "Postmark"
}
```

### MessageEvent

A message event. Occurs when a message [delivery or engagement status](/send-notifications/message-statuses) changes.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **data** (object) - The data associated with the message event. Only present for some event types.
- **id** (string) *required* - The unique identifier for the message event.
- **inserted_at** (string) *required* - Timestamp when the event was created.
- **recipient** (unknown) *required* - A reference to a recipient, either a user identifier (string) or an object reference (ID, collection).
- **type** (string) *required* - The type of event that occurred.

#### Example

```json
{
  "__typename": "MessageEvent",
  "data": null,
  "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
  "inserted_at": "2021-01-01T00:00:00Z",
  "recipient": "user_123",
  "type": "message.sent"
}
```

### ListMessagesResponse

A paginated list of messages.

#### Attributes

- **items** (array) *required* - A list of messages.
- **page_info** (object) *required* - Pagination information for a list of resources.

#### Example

```json
{
  "items": [
    {
      "__typename": "Message",
      "actors": [
        "mr_arnold",
        "mr_muldoon"
      ],
      "archived_at": null,
      "channel_id": "123e4567-e89b-12d3-a456-426614174000",
      "clicked_at": null,
      "data": {
        "affected_areas": [
          "visitor_center",
          "raptor_pen",
          "trex_paddock"
        ],
        "attraction_id": "paddock_rex_01",
        "evacuation_protocol": "active",
        "message": "Life finds a way",
        "severity": "critical",
        "system_status": "fences_failing"
      },
      "engagement_statuses": [
        "read",
        "seen"
      ],
      "id": "2w3YUpTTOxuDvZFji8OMsKrG176",
      "inserted_at": "1993-06-11T21:15:00Z",
      "interacted_at": null,
      "link_clicked_at": null,
      "metadata": {
        "external_id": "123e4567-e89b-12d3-a456-426614174000"
      },
      "read_at": "1993-06-11T21:30:00Z",
      "recipient": "dr_grant",
      "recipient_snapshot": {
        "email": "user@example.com",
        "name": "John Doe"
      },
      "scheduled_at": null,
      "seen_at": "1993-06-11T21:29:45Z",
      "source": {
        "__typename": "NotificationSource",
        "categories": [
          "security",
          "emergency"
        ],
        "key": "security-breach-alert",
        "step_ref": "alert_step_1",
        "version_id": "123e4567-e89b-12d3-a456-426614174000",
        "workflow_recipient_run_id": "def01234-a56b-78c9-d012-345678901bcd",
        "workflow_run_id": "789e0123-f45a-67b8-c901-234567890abc"
      },
      "status": "sent",
      "tenant": "ingen_isla_nublar",
      "updated_at": "1993-06-11T21:30:05Z",
      "workflow": "security-breach-alert"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### MessageContents

The content of a message.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **data** (object) *required* - Content data specific to the channel type.
- **inserted_at** (string) *required* - Timestamp when the message content was created.
- **message_id** (string) *required* - The unique identifier for the message content.

#### Example

```json
{
  "__typename": "MessageContent",
  "data": {
    "__typename": "MessageSmsContent",
    "body": "URGENT: Power failure detected in perimeter fencing. Backup generators failed to engage. Technical team dispatched. Maintain lockdown protocols.",
    "to": "+15553982647"
  },
  "inserted_at": "1993-06-11T20:30:00Z",
  "message_id": "2w3YUpTTOxuDvZFji8OMsKrG176"
}
```

### MessageInAppFeedButtonSetBlock

A button set block in a message in an app feed.

#### Attributes

- **buttons** (array) *required* - A list of buttons in an in app feed message.
- **name** (string) *required* - The name of the button set in a message in an app feed.
- **type** (string) *required* - The type of block in a message in an app feed.

#### Example

```json
{
  "buttons": [
    {
      "action": "action_1",
      "label": "Action 1",
      "name": "primary"
    }
  ],
  "name": "actions",
  "type": "button_set"
}
```

### MessageInAppFeedContentBlock

A block in a message in an app feed.

#### Attributes

- **content** (string) *required* - The content of the block in a message in an app feed.
- **name** (string) *required* - The name of the block in a message in an app feed.
- **rendered** (string) *required* - The rendered HTML version of the content.
- **type** (string) *required* - The type of block in a message in an app feed.

#### Example

```json
{
  "content": "This is a message in an app feed",
  "name": "body",
  "rendered": "<p>This is a message in an app feed</p>",
  "type": "markdown"
}
```

## Channels

A [Channel](/concepts/channels) is a delivery method for a message.

### Bulk

Bulk operations available for messages of a given channel.

#### Available endpoints

- **POST** `/v1/channels/{channel_id}/messages/bulk/{action}` - Bulk update message statuses for channel

### Bulk update message statuses for channel

Bulk update the status of messages for a specific channel. The channel is specified by the `channel_id` parameter. The action to perform is specified by the `action` parameter, where the action is a status change action (e.g. `archive`, `unarchive`).

#### Endpoint

`POST /v1/channels/{channel_id}/messages/bulk/{action}`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the channel to update messages for.
- **action** (string) *required* - The target status to be applied to the messages.

#### Request body

Updates message statuses in a specified channel. Use the `channel_id` parameter to target the channel and the `status` parameter to define what the status should be changed to (e.g. `archive`, `unarchive`). Apply to all messages or use filters to target a subset. For in-app channels, messages can be updated indefinitely via this operation. For all other channel types, messages outside the account's retention window will not be updated as part of this operation.

##### Example

```json
{
  "archived": "include",
  "delivery_status": "delivered",
  "engagement_status": "seen",
  "has_tenant": true,
  "newer_than": "2024-01-01T00:00:00Z",
  "older_than": "2024-01-01T00:00:00Z",
  "recipient_ids": [
    "recipient1",
    "recipient2"
  ],
  "tenants": [
    "tenant1",
    "tenant2"
  ],
  "trigger_data": "{\"key\":\"value\"}",
  "workflows": [
    "workflow1",
    "workflow2"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

## Users

A [User](/concepts/users) represents an individual in your system who can receive notifications through Knock. Users are the most common recipients of notifications and are always referenced by your internal identifier.

### Available endpoints

- **GET** `/v1/users/{user_id}` - Get user
- **GET** `/v1/users` - List users
- **PUT** `/v1/users/{user_id}` - Identify user
- **POST** `/v1/users/{user_id}/merge` - Merge users
- **DELETE** `/v1/users/{user_id}` - Delete user
- **GET** `/v1/users/{user_id}/messages` - List user messages
- **GET** `/v1/users/{user_id}/schedules` - List user schedules
- **GET** `/v1/users/{user_id}/subscriptions` - List user subscriptions
- **GET** `/v1/users/{user_id}/preferences` - List user preference sets
- **GET** `/v1/users/{user_id}/preferences/{id}` - Get user preference set
- **PUT** `/v1/users/{user_id}/preferences/{id}` - Update user preference set
- **DELETE** `/v1/users/{user_id}/preferences/{id}` - Delete user preference set
- **GET** `/v1/users/{user_id}/channel_data/{channel_id}` - Get channel data
- **PUT** `/v1/users/{user_id}/channel_data/{channel_id}` - Set channel data
- **DELETE** `/v1/users/{user_id}/channel_data/{channel_id}` - Unset channel data

### Get user

Retrieve a specific user by their ID.

#### Endpoint

`GET /v1/users/{user_id}`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The ID of the user to retrieve.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "User",
  "created_at": null,
  "email": "ian.malcolm@chaos.theory",
  "id": "user_id",
  "name": "Dr. Ian Malcolm",
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### List users

Retrieve a paginated list of users in the environment. Defaults to 50 users per page.

#### Endpoint

`GET /v1/users`

**Rate limit tier:** 4

#### Query parameters

- **include** (array) - Associated resources to include in the response.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "User",
      "created_at": null,
      "email": "ian.malcolm@chaos.theory",
      "id": "user_id",
      "name": "Dr. Ian Malcolm",
      "updated_at": "2024-05-22T12:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Identify user

Create or update a user with the provided identification data. When you identify an existing user, the system merges the properties you specific with what is currently set on the user, updating only the fields included in your requests.

#### Endpoint

`PUT /v1/users/{user_id}`

**Rate limit tier:** 3

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Request body

A set of parameters to identify a user with. Does not include the user ID, as that's specified elsewhere in the request. You can supply any additional properties you'd like to upsert for the user.

##### Example

```json
{
  "channel_data": {
    "97c5837d-c65c-4d54-aa39-080eeb81c69d": {
      "tokens": [
        "push_token_123"
      ]
    }
  },
  "email": "ian.malcolm@chaos.theory",
  "name": "Dr. Ian Malcolm",
  "preferences": {
    "default": {
      "channel_types": {
        "email": true
      },
      "workflows": {
        "dinosaurs-loose": {
          "channel_types": {
            "email": true
          }
        }
      }
    }
  },
  "timezone": "America/New_York"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "User",
  "created_at": null,
  "email": "ian.malcolm@chaos.theory",
  "id": "user_id",
  "name": "Dr. Ian Malcolm",
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Merge users

Merge two users together, where the user specified with the `from_user_id` param will be merged into the user specified by `user_id`.

#### Endpoint

`POST /v1/users/{user_id}/merge`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The id of the user to merge into.

#### Request body

A set of parameters to merge one user into another.

##### Example

```json
{
  "from_user_id": "user_1"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "User",
  "created_at": null,
  "email": "ian.malcolm@chaos.theory",
  "id": "user_id",
  "name": "Dr. Ian Malcolm",
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Delete user

Permanently delete a user and all associated data.

#### Endpoint

`DELETE /v1/users/{user_id}`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The ID of the user to delete.

#### Responses

##### 204

No Content

### List user messages

Returns a paginated list of messages for a specific user. Messages are sorted with the most recent ones appearing first. Messages outside the account's retention window will not be included in the results.

#### Endpoint

`GET /v1/users/{user_id}/messages`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The user ID to list messages for.

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).
- **tenant** (string) - Limits the results to items with the corresponding tenant.
- **channel_id** (string) - Limits the results to items with the corresponding channel ID.
- **status** (array) - Limits the results to messages with the given delivery status.
- **engagement_status** (array) - Limits the results to messages with the given engagement status.
- **message_ids** (array) - Limits the results to only the message IDs given (max 50). Note: when using this option, the results will be subject to any other filters applied to the query.
- **workflow_categories** (array) - Limits the results to messages related to any of the provided categories.
- **source** (string) - Limits the results to messages triggered by the given workflow key.
- **workflow_run_id** (string) - Limits the results to messages associated with the top-level workflow run ID returned by the workflow trigger request.
- **workflow_recipient_run_id** (string) - Limits the results to messages for a specific recipient's workflow run.
- **trigger_data** (string) - Limits the results to only messages that were generated with the given data. See [trigger data filtering](/api-reference/overview/trigger-data-filtering) for more information.
- **inserted_at.gt** (string) - Limits the results to items inserted after the given date.
- **inserted_at.gte** (string) - Limits the results to items inserted after or on the given date.
- **inserted_at.lt** (string) - Limits the results to items inserted before the given date.
- **inserted_at.lte** (string) - Limits the results to items inserted before or on the given date.

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "Message",
      "actors": [
        "mr_arnold",
        "mr_muldoon"
      ],
      "archived_at": null,
      "channel_id": "123e4567-e89b-12d3-a456-426614174000",
      "clicked_at": null,
      "data": {
        "affected_areas": [
          "visitor_center",
          "raptor_pen",
          "trex_paddock"
        ],
        "attraction_id": "paddock_rex_01",
        "evacuation_protocol": "active",
        "message": "Life finds a way",
        "severity": "critical",
        "system_status": "fences_failing"
      },
      "engagement_statuses": [
        "read",
        "seen"
      ],
      "id": "2w3YUpTTOxuDvZFji8OMsKrG176",
      "inserted_at": "1993-06-11T21:15:00Z",
      "interacted_at": null,
      "link_clicked_at": null,
      "metadata": {
        "external_id": "123e4567-e89b-12d3-a456-426614174000"
      },
      "read_at": "1993-06-11T21:30:00Z",
      "recipient": "dr_grant",
      "recipient_snapshot": {
        "email": "user@example.com",
        "name": "John Doe"
      },
      "scheduled_at": null,
      "seen_at": "1993-06-11T21:29:45Z",
      "source": {
        "__typename": "NotificationSource",
        "categories": [
          "security",
          "emergency"
        ],
        "key": "security-breach-alert",
        "step_ref": "alert_step_1",
        "version_id": "123e4567-e89b-12d3-a456-426614174000",
        "workflow_recipient_run_id": "def01234-a56b-78c9-d012-345678901bcd",
        "workflow_run_id": "789e0123-f45a-67b8-c901-234567890abc"
      },
      "status": "sent",
      "tenant": "ingen_isla_nublar",
      "updated_at": "1993-06-11T21:30:05Z",
      "workflow": "security-breach-alert"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List user schedules

Returns a paginated list of schedules for a specific user, in descending order.

#### Endpoint

`GET /v1/users/{user_id}/schedules`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The user ID to list schedules for.

#### Query parameters

- **workflow** (string) - The workflow key to filter schedules for.
- **tenant** (string) - The tenant ID to filter schedules for.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Schedule",
      "actor": null,
      "data": null,
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "inserted_at": "2021-01-01T00:00:00Z",
      "last_occurrence_at": null,
      "next_occurrence_at": null,
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "repeats": [
        {
          "__typename": "ScheduleRepeat",
          "day_of_month": null,
          "days": [
            "mon",
            "tue",
            "wed",
            "thu",
            "fri",
            "sat",
            "sun"
          ],
          "frequency": "daily",
          "hours": null,
          "interval": 1,
          "minutes": null
        }
      ],
      "tenant": null,
      "updated_at": "2021-01-01T00:00:00Z",
      "workflow": "workflow_123"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List user subscriptions

Retrieves a paginated list of subscriptions for a specific user, in descending order.

#### Endpoint

`GET /v1/users/{user_id}/subscriptions`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The user ID to list subscriptions for.

#### Query parameters

- **include** (array) - Associated resources to include in the response.
- **objects[]** (array) - Only returns subscriptions for the specified object references.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Subscription",
      "inserted_at": "2021-01-01T00:00:00Z",
      "object": {
        "__typename": "Object",
        "collection": "assets",
        "created_at": null,
        "id": "specimen_25",
        "properties": {
          "classification": "Theropod",
          "config": {
            "biz": "baz",
            "foo": "bar"
          },
          "name": "Velociraptor",
          "status": "contained"
        },
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "updated_at": "2021-01-01T00:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List user preference sets

Retrieves a list of all preference sets for a specific user.

#### Endpoint

`GET /v1/users/{user_id}/preferences`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "categories": {
      "marketing": false,
      "transactional": {
        "channel_types": {
          "email": false
        }
      }
    },
    "channel_types": {
      "email": true,
      "push": false,
      "sms": {
        "conditions": [
          {
            "argument": "US",
            "operator": "equal_to",
            "variable": "recipient.country_code"
          }
        ]
      }
    },
    "commercial_subscribed": true,
    "id": "default",
    "workflows": null
  }
]
```

### Get user preference set

Retrieves a specific preference set for a user identified by the preference set ID.

#### Endpoint

`GET /v1/users/{user_id}/preferences/{id}`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **id** (string) *required* - Unique identifier for the preference set.

#### Query parameters

- **tenant** (string) - The unique identifier for the tenant.

#### Responses

##### 200

OK

###### Example

```json
{
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true,
    "push": false,
    "sms": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    }
  },
  "commercial_subscribed": true,
  "id": "default",
  "workflows": null
}
```

### Update user preference set

Updates a complete preference set for a user. By default, this is a destructive operation and will replace any existing preferences with the preferences given. Use '__persistence_strategy__': 'merge' to merge with existing preferences instead.

#### Endpoint

`PUT /v1/users/{user_id}/preferences/{id}`

**Rate limit tier:** 3

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **id** (string) *required* - Unique identifier for the preference set.

#### Request body

A request to set a preference set for a recipient.

##### Example

```json
{
  "__persistence_strategy__": "merge",
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true
  },
  "channels": {
    "2f641633-95d3-4555-9222-9f1eb7888a80": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    },
    "aef6e715-df82-4ab6-b61e-b743e249f7b6": true
  },
  "commercial_subscribed": true,
  "workflows": {
    "dinosaurs-loose": {
      "channel_types": {
        "email": false
      }
    }
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true,
    "push": false,
    "sms": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    }
  },
  "commercial_subscribed": true,
  "id": "default",
  "workflows": null
}
```

### Delete user preference set

Unsets the preference set for the user, removing it entirely.

#### Endpoint

`DELETE /v1/users/{user_id}/preferences/{id}`

**Rate limit tier:** 3

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **id** (string) *required* - Unique identifier for the preference set.

#### Responses

##### 204

No Content

### Get channel data

Retrieves the channel data for a specific user and channel ID.

#### Endpoint

`GET /v1/users/{user_id}/channel_data/{channel_id}`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "ChannelData",
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "data": {
    "devices": [
      {
        "locale": null,
        "timezone": null,
        "token": "device_1"
      }
    ],
    "tokens": [
      "push_token_1"
    ]
  }
}
```

### Set channel data

Updates or creates channel data for a specific user and channel ID. If no user exists in the current environment for the given `user_id`, Knock will create the user entry as part of this request.

#### Endpoint

`PUT /v1/users/{user_id}/channel_data/{channel_id}`

**Rate limit tier:** 3

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Request body

A request to set channel data for a type of channel.

##### Example

```json
{
  "data": {
    "tokens": [
      "push_token_1"
    ]
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "ChannelData",
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "data": {
    "devices": [
      {
        "locale": null,
        "timezone": null,
        "token": "device_1"
      }
    ],
    "tokens": [
      "push_token_1"
    ]
  }
}
```

### Unset channel data

Deletes channel data for a specific user and channel ID.

#### Endpoint

`DELETE /v1/users/{user_id}/channel_data/{channel_id}`

**Rate limit tier:** 3

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Responses

##### 204

No Content

### Feeds

A feed exposes the messages delivered to an in-app feed channel, formatted specially to be consumed in a notification feed.

A feed will always return a list of `FeedItems`, which are pointers to a message delivered and contain all of the information needed in order to render an item within a notification feed.

**Note: Feeds are a specialized form of messages that are designed purely for in-app rendering, and as such return information that is required on the client to do so.**

#### Available endpoints

- **GET** `/v1/users/{user_id}/feeds/{id}` - List feed items
- **GET** `/v1/users/{user_id}/feeds/{id}/settings` - Get feed settings

### List feed items

Returns a paginated list of feed items for a user in reverse chronological order, including metadata about the feed. If the user has not yet been identified within Knock, an empty feed will be returned.

You can customize the response using [response filters](/integrations/in-app/knock#customizing-api-response-content) to exclude or only include specific properties on your resources.

**Notes:**
* When making this call from a client-side environment, use your publishable key along with a user token.
* This endpoint’s rate limit is always scoped per-user and per-environment. This is true even for requests made without a signed user token.
* Any [attachments](/integrations/email/attachments) present in trigger data are automatically excluded from both the `data` and `activities` fields of `UserInAppFeedResponse`.


#### Endpoint

`GET /v1/users/{user_id}/feeds/{id}`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **id** (string) *required* - The unique identifier for the channel.

#### Query parameters

- **status** (string) - The status of the feed items.
- **source** (string) - The workflow key associated with the message in the feed.
- **tenant** (string) - The tenant associated with the feed items.
- **has_tenant** (boolean) - Whether the feed items have a tenant.
- **workflow_categories** (array) - The workflow categories of the feed items.
- **archived** (string) - The archived status of the feed items.
- **trigger_data** (string) - The trigger data of the feed items (as a JSON string).
- **locale** (string) - The locale to render the feed items in. Must be in the IETF 5646 format (e.g. `en-US`). When not provided, will default to the locale that the feed items were rendered in. Only available for enterprise plan customers using custom translations.
- **exclude** (string) - Comma-separated list of field paths to exclude from the response. Use dot notation for nested fields (e.g., `entries.archived_at`). Limited to 3 levels deep.
- **mode** (string) - The mode to render the feed items in. Can be `compact` or `rich`. Defaults to `rich`. When `mode` is `compact`, feed items will not have `activities` and `total_activities` fields; the `data` field will not include nested arrays and objects; and the `actors` field will only have up to one actor.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).
- **inserted_at.gt** (string) - Limits the results to items inserted after the given date.
- **inserted_at.gte** (string) - Limits the results to items inserted after or on the given date.
- **inserted_at.lt** (string) - Limits the results to items inserted before the given date.
- **inserted_at.lte** (string) - Limits the results to items inserted before or on the given date.

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "FeedItem",
      "activities": [
        {
          "__typename": "Activity",
          "actor": null,
          "data": {
            "foo": "bar"
          },
          "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
          "inserted_at": "2024-01-01T00:00:00Z",
          "recipient": {
            "__typename": "User",
            "avatar": null,
            "created_at": null,
            "email": "jane@ingen.net",
            "id": "jane",
            "name": "Jane Doe",
            "phone_number": null,
            "timezone": null,
            "updated_at": "2024-05-22T12:00:00Z"
          },
          "updated_at": "2024-01-01T00:00:00Z"
        }
      ],
      "actors": [
        {
          "__typename": "User",
          "avatar": null,
          "created_at": null,
          "email": "jane@ingen.net",
          "id": "jane",
          "name": "Jane Doe",
          "phone_number": null,
          "timezone": null,
          "updated_at": "2024-05-22T12:00:00Z"
        }
      ],
      "blocks": [
        {
          "content": "This is a message in an app feed",
          "name": "body",
          "rendered": "<p>This is a message in an app feed</p>",
          "type": "markdown"
        }
      ],
      "data": {
        "foo": "bar"
      },
      "id": "2FVHPWxRqNuXQ9krvNP5A6Z4qXe",
      "inserted_at": "2021-01-01T00:00:00Z",
      "source": {
        "__typename": "Workflow",
        "categories": [
          "collaboration"
        ],
        "key": "my_source",
        "version_id": "123e4567-e89b-12d3-a456-426614174000"
      },
      "tenant": "acme_corp",
      "total_activities": 10,
      "total_actors": 5,
      "updated_at": "2021-01-01T00:00:00Z"
    }
  ],
  "meta": {
    "__typename": "FeedMetadata",
    "total_count": 100,
    "unread_count": 10,
    "unseen_count": 5
  },
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  },
  "vars": {
    "foo": "bar"
  }
}
```

### Get feed settings

Returns the feed settings for a user.

#### Endpoint

`GET /v1/users/{user_id}/feeds/{id}/settings`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **id** (string) *required* - The unique identifier for the channel.

#### Responses

##### 200

OK

###### Example

```json
{
  "features": {
    "branding_required": true
  }
}
```

### Guides

A [Guide](/concepts/guides) is a collection of steps that can be used to guide a user through a workflow.

#### Available endpoints

- **GET** `/v1/users/{user_id}/guides/{channel_id}` - List guides
- **PUT** `/v1/users/{user_id}/guides/messages/seen` - Mark guide as seen
- **PUT** `/v1/users/{user_id}/guides/messages/interacted` - Mark guide as interacted
- **PUT** `/v1/users/{user_id}/guides/messages/archived` - Mark guide as archived
- **DELETE** `/v1/users/{user_id}/guides/messages/archived` - Mark guide as unarchived
- **PUT** `/v1/users/{user_id}/guides/engagements/reset` - Reset guide engagement

### List guides

Returns a list of eligible in-app guides for a specific user and channel.

#### Endpoint

`GET /v1/users/{user_id}/guides/{channel_id}`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Query parameters

- **tenant** (string) - The tenant ID to use for targeting and rendering guides.
- **data** (string) - The data (JSON encoded object) to use for targeting and rendering guides.
- **type** (string) - The type of guides to filter by.

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Guide",
      "activation_url_patterns": [],
      "activation_url_rules": [
        {
          "argument": "/workflows",
          "directive": "allow",
          "operator": "contains",
          "variable": "pathname"
        },
        {
          "argument": "/guides",
          "directive": "allow",
          "operator": "equal_to",
          "variable": "pathname"
        }
      ],
      "active": true,
      "bypass_global_group_limit": false,
      "channel_id": "51b92f90-1504-4fda-95c1-495a3883bc4d",
      "dashboard_url": "https://dashboard.knock.app/~/guides/nps-survey",
      "id": "53595157-2fac-4a17-8dd7-e6603e32cb3a",
      "inserted_at": "2025-09-30T14:54:44.217756Z",
      "key": "nps-survey",
      "semver": "0.0.3",
      "steps": [
        {
          "content": {
            "companyName": "Knock",
            "showFeedbackSection": true,
            "showThanksToast": true
          },
          "message": {
            "archived_at": null,
            "id": "33hjnKRKNx9ISRlixVBjhpkh28J",
            "interacted_at": "2025-10-07T15:10:59.291Z",
            "link_clicked_at": null,
            "read_at": "2025-10-07T15:10:59.291Z",
            "seen_at": "2025-10-06T18:46:03.210Z"
          },
          "ref": "step_1",
          "schema_key": "nps-survey",
          "schema_semver": "0.0.3",
          "schema_variant_key": "default"
        }
      ],
      "type": "nps-survey",
      "updated_at": "2025-10-03T17:46:53.653663Z"
    },
    {
      "__typename": "Guide",
      "activation_url_patterns": [
        {
          "directive": "allow",
          "pathname": "/dairy/*"
        },
        {
          "directive": "allow",
          "pathname": "/produce",
          "search": "role=admin"
        },
        {
          "directive": "allow",
          "pathname": "/"
        }
      ],
      "activation_url_rules": [],
      "active": true,
      "bypass_global_group_limit": false,
      "channel_id": "51b92f90-1504-4fda-95c1-495a3883bc4d",
      "dashboard_url": "https://dashboard.knock.app/~/guides/changelog-card",
      "id": "4fc4503e-ef8b-473a-ae07-14800639d30c",
      "inserted_at": "2025-10-07T19:41:06.215233Z",
      "key": "changelog-card",
      "semver": "0.0.3",
      "steps": [
        {
          "content": {
            "body": "Lorem ipsum",
            "dismissible": false,
            "eyebrowText": "New in Knock",
            "image": {
              "action": "",
              "alt": "",
              "url": "https://bhoite.com/img/sculptures/2024/lander-r2/lander-r2.jpg"
            },
            "link": "https://dashboard.knock.app/knock/development/guides/changelog-card/editor",
            "title": "Changelog card"
          },
          "message": {
            "archived_at": null,
            "id": null,
            "interacted_at": null,
            "link_clicked_at": null,
            "read_at": null,
            "seen_at": null
          },
          "ref": "step_1",
          "schema_key": "changelog-card",
          "schema_semver": "0.0.3",
          "schema_variant_key": "default"
        }
      ],
      "type": "changelog-card",
      "updated_at": "2025-10-07T20:39:52.410146Z"
    }
  ],
  "guide_group_display_logs": {
    "default": "2025-08-16T00:47:14.025Z"
  },
  "guide_groups": [
    {
      "__typename": "GuideGroup",
      "display_interval": 3600,
      "display_sequence": [
        "nps-survey",
        "changelog-card"
      ],
      "inserted_at": "2025-07-24T21:06:27.394627Z",
      "key": "default",
      "updated_at": "2025-10-07T20:39:52.465400Z"
    }
  ],
  "ineligible_guides": [
    {
      "key": "onboarding-tour",
      "message": "User has archived this guide already",
      "reason": "marked_as_archived"
    },
    {
      "key": "premium-feature",
      "message": "User is not a member of the target audience",
      "reason": "not_in_target_audience"
    }
  ]
}
```

### Mark guide as seen

Records that a guide has been seen by a user, triggering any associated seen events.

#### Endpoint

`PUT /v1/users/{user_id}/guides/messages/seen`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Request body

A request to mark a guide as seen.

##### Example

```json
{
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "content": {
    "body": "Limited spots available for today's behind-the-scenes DNA extraction demonstration.",
    "title": "DNA Lab Tour Available"
  },
  "data": {
    "next_time": "14:30",
    "spots_left": 8,
    "tour_id": "dna_lab_tour"
  },
  "guide_id": "7e9dc78c-b3b1-4127-a54e-71f1899b831a",
  "guide_key": "tour_notification",
  "guide_step_ref": "lab_tours",
  "tenant": "ingen_isla_nublar"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "status": "ok"
}
```

### Mark guide as interacted

Records that a user has interacted with a guide, triggering any associated interacted events.

#### Endpoint

`PUT /v1/users/{user_id}/guides/messages/interacted`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Request body

A request to mark a guide as interacted with.

##### Example

```json
{
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "guide_id": "7e9dc78c-b3b1-4127-a54e-71f1899b831a",
  "guide_key": "tour_notification",
  "guide_step_ref": "lab_tours",
  "metadata": {
    "cta": "Reserve Spot",
    "theme": "amber",
    "type": "banner"
  },
  "tenant": "ingen_isla_nublar"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "status": "ok"
}
```

### Mark guide as archived

Records that a guide has been archived by a user, triggering any associated archived events.

#### Endpoint

`PUT /v1/users/{user_id}/guides/messages/archived`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Request body

A request to mark a guide as archived.

##### Example

```json
{
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "guide_id": "7e9dc78c-b3b1-4127-a54e-71f1899b831a",
  "guide_key": "tour_notification",
  "guide_step_ref": "lab_tours",
  "is_final": false,
  "tenant": "ingen_isla_nublar",
  "unthrottled": false
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "status": "ok"
}
```

### Mark guide as unarchived

Records that a guide has been unarchived, triggering any associated unarchived events.

#### Endpoint

`DELETE /v1/users/{user_id}/guides/messages/archived`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Request body

A request to mark a guide as unarchived.

##### Example

```json
{
  "guide_key": "tour_notification",
  "tenant": "ingen_isla_nublar"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "status": "ok"
}
```

### Reset guide engagement

Resets the engagement state of a guide for a user, removing the guide's engagement log entry so the next interaction creates a fresh engagement.

#### Endpoint

`PUT /v1/users/{user_id}/guides/engagements/reset`

**Rate limit tier:** 2

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Request body

A request to reset a guide's engagement state.

##### Example

```json
{
  "guide_key": "tour_notification",
  "tenant": "ingen_isla_nublar"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "status": "ok"
}
```

### GuideArchivedRequest

A request to mark a guide as archived.

#### Attributes

- **channel_id** (string) *required* - The unique identifier for the channel.
- **guide_id** (string) *required* - The unique identifier for the guide.
- **guide_key** (string) *required* - The key of the guide.
- **guide_step_ref** (string) *required* - The step reference of the guide.
- **is_final** (boolean) - Whether the guide is final.
- **tenant** (string) - The tenant ID of the guide.
- **unthrottled** (boolean) - Whether the guide bypasses its guide group's throttle settings. When true, archiving the guide does not open a new throttle window.

#### Example

```json
{
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "guide_id": "7e9dc78c-b3b1-4127-a54e-71f1899b831a",
  "guide_key": "tour_notification",
  "guide_step_ref": "lab_tours",
  "is_final": false,
  "tenant": "ingen_isla_nublar",
  "unthrottled": false
}
```

### GuideActionResponse

A response for a guide action.

#### Attributes

- **status** (string) *required* - The status of a guide's action.

#### Example

```json
{
  "status": "ok"
}
```

### GuideInteractedRequest

A request to mark a guide as interacted with.

#### Attributes

- **channel_id** (string) *required* - The unique identifier for the channel.
- **guide_id** (string) *required* - The unique identifier for the guide.
- **guide_key** (string) *required* - The key of the guide.
- **guide_step_ref** (string) *required* - The step reference of the guide.
- **metadata** (object) - Metadata about the interaction.
- **tenant** (string) - The tenant ID of the guide.

#### Example

```json
{
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "guide_id": "7e9dc78c-b3b1-4127-a54e-71f1899b831a",
  "guide_key": "tour_notification",
  "guide_step_ref": "lab_tours",
  "metadata": {
    "cta": "Reserve Spot",
    "theme": "amber",
    "type": "banner"
  },
  "tenant": "ingen_isla_nublar"
}
```

### GuideSeenRequest

A request to mark a guide as seen.

#### Attributes

- **channel_id** (string) *required* - The unique identifier for the channel.
- **content** (object) *required* - The content of the guide.
- **data** (object) - The data of the guide.
- **guide_id** (string) *required* - The unique identifier for the guide.
- **guide_key** (string) *required* - The key of the guide.
- **guide_step_ref** (string) *required* - The step reference of the guide.
- **tenant** (string) - The tenant ID of the guide.

#### Example

```json
{
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "content": {
    "body": "Limited spots available for today's behind-the-scenes DNA extraction demonstration.",
    "title": "DNA Lab Tour Available"
  },
  "data": {
    "next_time": "14:30",
    "spots_left": 8,
    "tour_id": "dna_lab_tour"
  },
  "guide_id": "7e9dc78c-b3b1-4127-a54e-71f1899b831a",
  "guide_key": "tour_notification",
  "guide_step_ref": "lab_tours",
  "tenant": "ingen_isla_nublar"
}
```

### Bulk operations

Bulk operations available for users. These endpoints return a BulkOperation that executes the job asynchronously. Progress can be tracked via the [Bulk operations API](/api-reference/bulk_operations).

#### Available endpoints

- **POST** `/v1/users/bulk/identify` - Bulk identify users
- **POST** `/v1/users/bulk/preferences` - Bulk set preferences
- **POST** `/v1/users/bulk/delete` - Bulk delete users

### Bulk identify users

Identifies multiple users in a single operation. Allows creating or updating up to 1,000 users in a single batch with various properties, preferences, and channel data.

#### Endpoint

`POST /v1/users/bulk/identify`

**Rate limit tier:** 1

#### Request body

A request to identify a list of users.

##### Example

```json
{
  "users": [
    {
      "email": "jane@ingen.net",
      "id": "user_1",
      "name": "Jane Doe",
      "timezone": "America/New_York"
    }
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Bulk set preferences

Bulk sets the preferences for up to 1,000 users at a time. The preference set `:id` can be either `default` or a `tenant.id`. Learn more about [per-tenant preferences](/preferences/tenant-preferences). Note that this is a destructive operation and will replace any existing users' preferences with the preferences sent.

#### Endpoint

`POST /v1/users/bulk/preferences`

**Rate limit tier:** 1

#### Request body

A request to set preferences for a set of users in bulk.

##### Example

```json
{
  "preferences": {
    "categories": {
      "marketing": false,
      "transactional": {
        "channel_types": {
          "email": false
        }
      }
    },
    "channel_types": {
      "email": true
    },
    "channels": {
      "2f641633-95d3-4555-9222-9f1eb7888a80": {
        "conditions": [
          {
            "argument": "US",
            "operator": "equal_to",
            "variable": "recipient.country_code"
          }
        ]
      },
      "aef6e715-df82-4ab6-b61e-b743e249f7b6": true
    },
    "commercial_subscribed": true,
    "id": "default",
    "workflows": {
      "dinosaurs-loose": {
        "channel_types": {
          "email": false
        }
      }
    }
  },
  "user_ids": [
    "user_1",
    "user_2"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Bulk delete users

Permanently deletes up to 1,000 users at a time.

#### Endpoint

`POST /v1/users/bulk/delete`

**Rate limit tier:** 1

#### Request body

A request to delete users in bulk.

##### Example

```json
{
  "user_ids": [
    "user_1",
    "user_2"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Preference center

Use the preference center API to retrieve dashboard-managed configuration for a custom preference center or generate a user-specific signed URL for Knock's hosted preference center.

#### Available endpoints

- **GET** `/v1/users/{user_id}/preference_center/config` - Get preference center config
- **POST** `/v1/users/{user_id}/preference_center/signed_url` - Create preference center signed URL

### Get preference center config

Returns the preference center config with environment metadata for the given user.

#### Endpoint

`GET /v1/users/{user_id}/preference_center/config`

**Rate limit tier:** 4

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Responses

##### 200

OK

###### Example

```json
{
  "account_name": "Acme Inc.",
  "branding": {
    "dark": {
      "icon_url": "https://example.com/icon-dark.png",
      "logo_url": "https://example.com/logo-dark.png",
      "primary_color": "#C02727",
      "primary_color_contrast": "#11E2EC"
    },
    "icon_url": "https://example.com/icon.png",
    "logo_url": "https://example.com/logo.png",
    "primary_color": "#0EA5E9",
    "primary_color_contrast": "#0F172A"
  },
  "config": {
    "body": "Choose which notifications you want to receive.",
    "rows": [
      {
        "channel_types": [],
        "description": "Opt out of receiving comment and reply notifications",
        "identifier": "comments",
        "name": "Comments and replies",
        "type": "category"
      },
      {
        "channel_types": [
          "email",
          "sms"
        ],
        "description": "Receive notifications from the following channel types",
        "name": "Channel Types",
        "type": "channel_types"
      }
    ],
    "show_account_name": true,
    "title": "Notification preferences"
  },
  "enabled": true,
  "knock_branding_required": false,
  "user_email": "user@example.com"
}
```

### Create preference center signed URL

Generates a signed preference center URL and token for the given user in the current environment.

#### Endpoint

`POST /v1/users/{user_id}/preference_center/signed_url`

**Rate limit tier:** 3

#### Path parameters

- **user_id** (string) *required* - The unique identifier of the user.

#### Responses

##### 200

OK

###### Example

```json
{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "url": "https://p.knock.app/p/eyJhbGciOiJIUzI1NiJ9..."
}
```

### PreferenceCenterBrandingConfig

The branding for the preference center, sourced from public environment variables.

#### Attributes

- **icon_url** (string) - The icon URL for the preference center. Must point to a valid image with an image MIME type.
- **logo_url** (string) - The logo URL for the preference center. Must point to a valid image with an image MIME type.
- **primary_color** (string) - The primary color for the preference center, provided as a hex value.
- **primary_color_contrast** (string) - The primary color contrast for the preference center, provided as a hex value.

#### Example

```json
{
  "icon_url": "https://example.com/icon.png",
  "logo_url": "https://example.com/logo.png",
  "primary_color": "#0EA5E9",
  "primary_color_contrast": "#0F172A"
}
```

### User

A [User](/concepts/users) represents an individual in your system who can receive notifications through Knock. Users are the most common recipients of notifications and are always referenced by your internal identifier.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **avatar** (string) - A URL for the avatar of the user.
- **created_at** (string) - The creation date of the user from your system.
- **email** (string) - The primary email address for the user.
- **id** (string) *required* - The unique identifier of the user.
- **name** (string) - Display name of the user.
- **phone_number** (string) - The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the user (required for SMS channels).
- **timezone** (string) - The timezone of the user. Must be a valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Used for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).
- **updated_at** (string) *required* - The timestamp when the resource was last updated.

#### Example

```json
{
  "__typename": "User",
  "created_at": null,
  "email": "ian.malcolm@chaos.theory",
  "id": "user_id",
  "name": "Dr. Ian Malcolm",
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### IdentifyUserRequest

A set of parameters to identify a user with. Does not include the user ID, as that's specified elsewhere in the request. You can supply any additional properties you'd like to upsert for the user.

#### Attributes

- **avatar** (string) - A URL for the avatar of the user.
- **channel_data** (unknown) - Channel-specific information that's needed to deliver a notification to an end provider.
- **created_at** (string) - The creation date of the user from your system.
- **email** (string) - The primary email address for the user.
- **locale** (string) - The locale of the user. Used for [message localization](/concepts/translations).
- **name** (string) - Display name of the user.
- **phone_number** (string) - The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the user (required for SMS channels).
- **preferences** (unknown) - A set of preferences for the user.
- **timezone** (string) - The timezone of the user. Must be a valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Used for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).

#### Example

```json
{
  "channel_data": {
    "97c5837d-c65c-4d54-aa39-080eeb81c69d": {
      "tokens": [
        "push_token_123"
      ]
    }
  },
  "email": "ian.malcolm@chaos.theory",
  "name": "Dr. Ian Malcolm",
  "preferences": {
    "default": {
      "channel_types": {
        "email": true
      },
      "workflows": {
        "dinosaurs-loose": {
          "channel_types": {
            "email": true
          }
        }
      }
    }
  },
  "timezone": "America/New_York"
}
```

### InlineIdentifyUserRequest

A set of parameters to inline-identify a user with. Inline identifying the user will ensure that the user is available before the request is executed in Knock. It will perform an upsert for the user you're supplying, replacing any properties specified.

#### Attributes

- **avatar** (string) - A URL for the avatar of the user.
- **channel_data** (unknown) - Channel-specific information that's needed to deliver a notification to an end provider.
- **created_at** (string) - The creation date of the user from your system.
- **email** (string) - The primary email address for the user.
- **id** (string) *required* - The unique identifier of the user.
- **locale** (string) - The locale of the user. Used for [message localization](/concepts/translations).
- **name** (string) - Display name of the user.
- **phone_number** (string) - The [E.164](https://www.twilio.com/docs/glossary/what-e164) phone number of the user (required for SMS channels).
- **preferences** (unknown) - A set of preferences for the user.
- **timezone** (string) - The timezone of the user. Must be a valid [tz database time zone string](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Used for [recurring schedules](/concepts/schedules#scheduling-workflows-with-recurring-schedules-for-recipients).

#### Example

```json
{
  "channel_data": {
    "97c5837d-c65c-4d54-aa39-080eeb81c69d": {
      "tokens": [
        "push_token_123"
      ]
    }
  },
  "email": "jane@ingen.net",
  "id": "user_1",
  "name": "Jane Doe",
  "preferences": {
    "default": {
      "channel_types": {
        "email": true
      },
      "workflows": {
        "dinosaurs-loose": {
          "channel_types": {
            "email": true
          }
        }
      }
    }
  },
  "timezone": "America/New_York"
}
```

### PreferenceSetCommercialSubscribedSetting

A set of settings for the commercial subscribed preference. Currently, this can only be a list of conditions to apply.

#### Attributes

- **conditions** (array) *required* - A list of conditions to apply to the commercial subscribed preference.

#### Example

```json
{
  "conditions": [
    {
      "argument": "false",
      "operator": "not_equal_to",
      "variable": "tenant.settings.preferences.commercial_subscribed"
    }
  ]
}
```

### ListSchedulesResponse

A response containing a list of schedules.

#### Attributes

- **entries** (array) *required* - A list of schedules.
- **page_info** (object) *required* - Pagination information for a list of resources.

#### Example

```json
{
  "entries": [
    {
      "__typename": "Schedule",
      "actor": null,
      "data": null,
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "inserted_at": "2021-01-01T00:00:00Z",
      "last_occurrence_at": null,
      "next_occurrence_at": null,
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "repeats": [
        {
          "__typename": "ScheduleRepeat",
          "day_of_month": null,
          "days": [
            "mon",
            "tue",
            "wed",
            "thu",
            "fri",
            "sat",
            "sun"
          ],
          "frequency": "daily",
          "hours": null,
          "interval": 1,
          "minutes": null
        }
      ],
      "tenant": null,
      "updated_at": "2021-01-01T00:00:00Z",
      "workflow": "workflow_123"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### ListSubscriptionsResponse

A response containing a list of subscriptions.

#### Attributes

- **entries** (array) *required* - A list of subscriptions.
- **page_info** (object) *required* - Pagination information for a list of resources.

#### Example

```json
{
  "entries": [
    {
      "__typename": "Subscription",
      "inserted_at": "2021-01-01T00:00:00Z",
      "object": {
        "__typename": "Object",
        "collection": "assets",
        "created_at": null,
        "id": "specimen_25",
        "properties": {
          "classification": "Theropod",
          "config": {
            "biz": "baz",
            "foo": "bar"
          },
          "name": "Velociraptor",
          "status": "contained"
        },
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "updated_at": "2021-01-01T00:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

## Objects

An [Object](/concepts/objects) represents a resource in your system that you've stored in Knock. It can be used to send out-of-app notifications to non-user recipients (such as a public channel in a chat app), or to trigger notifications to [subscribers](/concepts/subscriptions) of a non-user resource such as a shared document.

### Available endpoints

- **PUT** `/v1/objects/{collection}/{id}` - Set an object
- **GET** `/v1/objects/{collection}/{id}` - Get an object
- **GET** `/v1/objects/{collection}` - List objects in a collection
- **DELETE** `/v1/objects/{collection}/{id}` - Delete an object
- **GET** `/v1/objects/{collection}/{object_id}/preferences` - List preference sets
- **GET** `/v1/objects/{collection}/{object_id}/preferences/{id}` - Get object preference set
- **PUT** `/v1/objects/{collection}/{object_id}/preferences/{id}` - Update a preference set
- **DELETE** `/v1/objects/{collection}/{object_id}/preferences/{id}` - Delete object preference set
- **GET** `/v1/objects/{collection}/{id}/schedules` - List object schedules
- **GET** `/v1/objects/{collection}/{id}/messages` - List messages
- **GET** `/v1/objects/{collection}/{object_id}/channel_data/{channel_id}` - Get channel data
- **PUT** `/v1/objects/{collection}/{object_id}/channel_data/{channel_id}` - Set channel data
- **DELETE** `/v1/objects/{collection}/{object_id}/channel_data/{channel_id}` - Unset channel data
- **GET** `/v1/objects/{collection}/{object_id}/subscriptions` - List subscriptions
- **POST** `/v1/objects/{collection}/{object_id}/subscriptions` - Add subscriptions
- **DELETE** `/v1/objects/{collection}/{object_id}/subscriptions` - Delete subscriptions

### Set an object

Creates a new object or updates an existing one in the specified collection. This operation is used to identify objects with their properties, as well as optional preferences and channel data.

#### Endpoint

`PUT /v1/objects/{collection}/{id}`

**Rate limit tier:** 3

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the object.

#### Request body

A set of parameters to set an object with. Does not include the object id or collection.

##### Example

```json
{
  "channel_data": {
    "97c5837d-c65c-4d54-aa39-080eeb81c69d": {
      "tokens": [
        "push_token_123"
      ]
    }
  },
  "description": "My product description",
  "locale": "en-US",
  "name": "My product",
  "preferences": {
    "default": {
      "channel_types": {
        "email": true
      },
      "workflows": {
        "dinosaurs-loose": {
          "channel_types": {
            "email": true
          }
        }
      }
    }
  },
  "price": 100,
  "timezone": "America/New_York"
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Object",
  "collection": "assets",
  "created_at": null,
  "id": "specimen_25",
  "properties": {
    "classification": "Theropod",
    "config": {
      "biz": "baz",
      "foo": "bar"
    },
    "name": "Velociraptor",
    "status": "contained"
  },
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Get an object

Retrieves a specific object by its ID from the specified collection. Returns the object with all its properties.

#### Endpoint

`GET /v1/objects/{collection}/{id}`

**Rate limit tier:** 4

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the object.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Object",
  "collection": "assets",
  "created_at": null,
  "id": "specimen_25",
  "properties": {
    "classification": "Theropod",
    "config": {
      "biz": "baz",
      "foo": "bar"
    },
    "name": "Velociraptor",
    "status": "contained"
  },
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### List objects in a collection

Returns a paginated list of objects from the specified collection. Optionally includes preference data for the objects.

#### Endpoint

`GET /v1/objects/{collection}`

**Rate limit tier:** 4

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).
- **include** (array) - Includes preferences of the objects in the response.

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Object",
      "collection": "assets",
      "created_at": null,
      "id": "specimen_25",
      "properties": {
        "classification": "Theropod",
        "config": {
          "biz": "baz",
          "foo": "bar"
        },
        "name": "Velociraptor",
        "status": "contained"
      },
      "updated_at": "2024-05-22T12:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Delete an object

Permanently removes an object from the specified collection. This operation cannot be undone.

#### Endpoint

`DELETE /v1/objects/{collection}/{id}`

**Rate limit tier:** 3

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the object.

#### Responses

##### 204

No Content

### List preference sets

Returns a paginated list of preference sets for the specified object.

#### Endpoint

`GET /v1/objects/{collection}/{object_id}/preferences`

**Rate limit tier:** 4

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "categories": {
      "marketing": false,
      "transactional": {
        "channel_types": {
          "email": false
        }
      }
    },
    "channel_types": {
      "email": true,
      "push": false,
      "sms": {
        "conditions": [
          {
            "argument": "US",
            "operator": "equal_to",
            "variable": "recipient.country_code"
          }
        ]
      }
    },
    "commercial_subscribed": true,
    "id": "default",
    "workflows": null
  }
]
```

### Get object preference set

Returns the preference set for the specified object and preference set `id`.

#### Endpoint

`GET /v1/objects/{collection}/{object_id}/preferences/{id}`

**Rate limit tier:** 4

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the preference set.

#### Responses

##### 200

OK

###### Example

```json
{
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true,
    "push": false,
    "sms": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    }
  },
  "commercial_subscribed": true,
  "id": "default",
  "workflows": null
}
```

### Update a preference set

Sets preferences within the given preference set. By default, this is a destructive operation and will replace any existing preferences with the preferences given. Use '__persistence_strategy': 'merge' to merge with existing preferences instead. If no object exists in the current environment for the given `:collection` and `:object_id`, Knock will create the object as part of this request. The preference set `:id` can be either `default` or a `tenant.id`. Learn more about [per-tenant preferences](/preferences/tenant-preferences).

#### Endpoint

`PUT /v1/objects/{collection}/{object_id}/preferences/{id}`

**Rate limit tier:** 3

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the preference set.

#### Request body

A request to set a preference set for a recipient.

##### Example

```json
{
  "__persistence_strategy__": "merge",
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true
  },
  "channels": {
    "2f641633-95d3-4555-9222-9f1eb7888a80": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    },
    "aef6e715-df82-4ab6-b61e-b743e249f7b6": true
  },
  "commercial_subscribed": true,
  "workflows": {
    "dinosaurs-loose": {
      "channel_types": {
        "email": false
      }
    }
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true,
    "push": false,
    "sms": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    }
  },
  "commercial_subscribed": true,
  "id": "default",
  "workflows": null
}
```

### Delete object preference set

Unsets the preference set for the object, removing it entirely.

#### Endpoint

`DELETE /v1/objects/{collection}/{object_id}/preferences/{id}`

**Rate limit tier:** 3

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the preference set.

#### Responses

##### 204

No Content

### List object schedules

Returns a paginated list of schedules for an object.

#### Endpoint

`GET /v1/objects/{collection}/{id}/schedules`

**Rate limit tier:** 4

#### Path parameters

- **id** (string) *required* - The ID of the object to list schedules for.
- **collection** (string) *required* - The collection of the object to list schedules for.

#### Query parameters

- **tenant** (string) - Filter schedules by tenant id.
- **workflow** (string) - Filter schedules by workflow id.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Schedule",
      "actor": null,
      "data": null,
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "inserted_at": "2021-01-01T00:00:00Z",
      "last_occurrence_at": null,
      "next_occurrence_at": null,
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "repeats": [
        {
          "__typename": "ScheduleRepeat",
          "day_of_month": null,
          "days": [
            "mon",
            "tue",
            "wed",
            "thu",
            "fri",
            "sat",
            "sun"
          ],
          "frequency": "daily",
          "hours": null,
          "interval": 1,
          "minutes": null
        }
      ],
      "tenant": null,
      "updated_at": "2021-01-01T00:00:00Z",
      "workflow": "workflow_123"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### List messages

Returns a paginated list of messages for a specific object in the given collection. Allows filtering by message status and provides various sorting options.

#### Endpoint

`GET /v1/objects/{collection}/{id}/messages`

**Rate limit tier:** 4

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.
- **id** (string) *required* - Unique identifier for the object.

#### Query parameters

- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).
- **tenant** (string) - Limits the results to items with the corresponding tenant.
- **channel_id** (string) - Limits the results to items with the corresponding channel ID.
- **status** (array) - Limits the results to messages with the given delivery status.
- **engagement_status** (array) - Limits the results to messages with the given engagement status.
- **message_ids** (array) - Limits the results to only the message IDs given (max 50). Note: when using this option, the results will be subject to any other filters applied to the query.
- **workflow_categories** (array) - Limits the results to messages related to any of the provided categories.
- **source** (string) - Limits the results to messages triggered by the given workflow key.
- **workflow_run_id** (string) - Limits the results to messages associated with the top-level workflow run ID returned by the workflow trigger request.
- **workflow_recipient_run_id** (string) - Limits the results to messages for a specific recipient's workflow run.
- **trigger_data** (string) - Limits the results to only messages that were generated with the given data. See [trigger data filtering](/api-reference/overview/trigger-data-filtering) for more information.
- **inserted_at.gt** (string) - Limits the results to items inserted after the given date.
- **inserted_at.gte** (string) - Limits the results to items inserted after or on the given date.
- **inserted_at.lt** (string) - Limits the results to items inserted before the given date.
- **inserted_at.lte** (string) - Limits the results to items inserted before or on the given date.

#### Responses

##### 200

OK

###### Example

```json
{
  "items": [
    {
      "__typename": "Message",
      "actors": [
        "mr_arnold",
        "mr_muldoon"
      ],
      "archived_at": null,
      "channel_id": "123e4567-e89b-12d3-a456-426614174000",
      "clicked_at": null,
      "data": {
        "affected_areas": [
          "visitor_center",
          "raptor_pen",
          "trex_paddock"
        ],
        "attraction_id": "paddock_rex_01",
        "evacuation_protocol": "active",
        "message": "Life finds a way",
        "severity": "critical",
        "system_status": "fences_failing"
      },
      "engagement_statuses": [
        "read",
        "seen"
      ],
      "id": "2w3YUpTTOxuDvZFji8OMsKrG176",
      "inserted_at": "1993-06-11T21:15:00Z",
      "interacted_at": null,
      "link_clicked_at": null,
      "metadata": {
        "external_id": "123e4567-e89b-12d3-a456-426614174000"
      },
      "read_at": "1993-06-11T21:30:00Z",
      "recipient": "dr_grant",
      "recipient_snapshot": {
        "email": "user@example.com",
        "name": "John Doe"
      },
      "scheduled_at": null,
      "seen_at": "1993-06-11T21:29:45Z",
      "source": {
        "__typename": "NotificationSource",
        "categories": [
          "security",
          "emergency"
        ],
        "key": "security-breach-alert",
        "step_ref": "alert_step_1",
        "version_id": "123e4567-e89b-12d3-a456-426614174000",
        "workflow_recipient_run_id": "def01234-a56b-78c9-d012-345678901bcd",
        "workflow_run_id": "789e0123-f45a-67b8-c901-234567890abc"
      },
      "status": "sent",
      "tenant": "ingen_isla_nublar",
      "updated_at": "1993-06-11T21:30:05Z",
      "workflow": "security-breach-alert"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Get channel data

Returns the channel data for the specified object and channel.

#### Endpoint

`GET /v1/objects/{collection}/{object_id}/channel_data/{channel_id}`

**Rate limit tier:** 4

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "ChannelData",
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "data": {
    "devices": [
      {
        "locale": null,
        "timezone": null,
        "token": "device_1"
      }
    ],
    "tokens": [
      "push_token_1"
    ]
  }
}
```

### Set channel data

Sets the channel data for the specified object and channel. If no object exists in the current environment for the given `collection` and `object_id`, Knock will create the object as part of this request.

#### Endpoint

`PUT /v1/objects/{collection}/{object_id}/channel_data/{channel_id}`

**Rate limit tier:** 3

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Request body

A request to set channel data for a type of channel.

##### Example

```json
{
  "data": {
    "tokens": [
      "push_token_1"
    ]
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "ChannelData",
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "data": {
    "devices": [
      {
        "locale": null,
        "timezone": null,
        "token": "device_1"
      }
    ],
    "tokens": [
      "push_token_1"
    ]
  }
}
```

### Unset channel data

Unsets the channel data for the specified object and channel.

#### Endpoint

`DELETE /v1/objects/{collection}/{object_id}/channel_data/{channel_id}`

**Rate limit tier:** 3

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.
- **channel_id** (string) *required* - The unique identifier for the channel.

#### Responses

##### 204

No Content

### List subscriptions

List subscriptions for an object. Either list the recipients that subscribe to the provided object, or list the objects that the provided object is subscribed to. Determined by the `mode` query parameter.

#### Endpoint

`GET /v1/objects/{collection}/{object_id}/subscriptions`

**Rate limit tier:** 4

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.

#### Query parameters

- **mode** (string) - Mode of the request. `recipient` to list the objects that the provided object is subscribed to, `object` to list the recipients that subscribe to the provided object.
- **include** (array) - Additional fields to include in the response.
- **recipients[]** (array) - Recipients to filter by (only used if mode is `object`).
- **objects[]** (array) - Objects to filter by (only used if mode is `recipient`).
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Subscription",
      "inserted_at": "2021-01-01T00:00:00Z",
      "object": {
        "__typename": "Object",
        "collection": "assets",
        "created_at": null,
        "id": "specimen_25",
        "properties": {
          "classification": "Theropod",
          "config": {
            "biz": "baz",
            "foo": "bar"
          },
          "name": "Velociraptor",
          "status": "contained"
        },
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "updated_at": "2021-01-01T00:00:00Z"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Add subscriptions

Add subscriptions for an object. If a subscription already exists, it will be updated. This endpoint also handles [inline identifications](/managing-recipients/identifying-recipients#inline-identifying-recipients) for the `recipient`.

#### Endpoint

`POST /v1/objects/{collection}/{object_id}/subscriptions`

**Rate limit tier:** 3

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.

#### Request body

A request to upsert subscriptions for a set of recipients.

##### Example

```json
{
  "properties": {
    "key": "value"
  },
  "recipients": [
    "user_1",
    "user_2"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Subscription",
    "inserted_at": "2021-01-01T00:00:00Z",
    "object": {
      "__typename": "Object",
      "collection": "assets",
      "created_at": null,
      "id": "specimen_25",
      "properties": {
        "classification": "Theropod",
        "config": {
          "biz": "baz",
          "foo": "bar"
        },
        "name": "Velociraptor",
        "status": "contained"
      },
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "recipient": {
      "__typename": "User",
      "avatar": null,
      "created_at": null,
      "email": "jane@ingen.net",
      "id": "jane",
      "name": "Jane Doe",
      "phone_number": null,
      "timezone": null,
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "updated_at": "2021-01-01T00:00:00Z"
  }
]
```

### Delete subscriptions

Delete subscriptions for the specified recipients from an object. Returns the list of deleted subscriptions.

#### Endpoint

`DELETE /v1/objects/{collection}/{object_id}/subscriptions`

**Rate limit tier:** 3

#### Path parameters

- **object_id** (string) *required* - Unique identifier for the object.
- **collection** (string) *required* - The collection this object belongs to.

#### Request body

A request to delete subscriptions for a set of recipients.

##### Example

```json
{
  "recipients": [
    "user_123"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Subscription",
    "inserted_at": "2021-01-01T00:00:00Z",
    "object": {
      "__typename": "Object",
      "collection": "assets",
      "created_at": null,
      "id": "specimen_25",
      "properties": {
        "classification": "Theropod",
        "config": {
          "biz": "baz",
          "foo": "bar"
        },
        "name": "Velociraptor",
        "status": "contained"
      },
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "recipient": {
      "__typename": "User",
      "avatar": null,
      "created_at": null,
      "email": "jane@ingen.net",
      "id": "jane",
      "name": "Jane Doe",
      "phone_number": null,
      "timezone": null,
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "updated_at": "2021-01-01T00:00:00Z"
  }
]
```

### Bulk operations

Bulk operations available for objects. These endpoints return a BulkOperation that executes the job asynchronously. Progress can be tracked via the [Bulk operations API](/api-reference/bulk_operations).

#### Available endpoints

- **POST** `/v1/objects/{collection}/bulk/set` - Bulk set objects
- **POST** `/v1/objects/{collection}/bulk/subscriptions/add` - Bulk add subscriptions
- **POST** `/v1/objects/{collection}/bulk/delete` - Bulk delete objects
- **POST** `/v1/objects/{collection}/bulk/subscriptions/delete` - Bulk delete subscriptions

### Bulk set objects

Bulk sets up to 1,000 objects at a time in the specified collection.

#### Endpoint

`POST /v1/objects/{collection}/bulk/set`

**Rate limit tier:** 1

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.

#### Request body

A request to set objects in bulk.

##### Example

```json
{
  "objects": [
    {
      "id": "project_1",
      "name": "My project"
    }
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Bulk add subscriptions

Add subscriptions for all objects in a single collection. If a subscription for an object in the collection already exists, it will be updated. This endpoint also handles [inline identifications](/managing-recipients/identifying-recipients#inline-identifying-recipients) for the `recipient` field.

#### Endpoint

`POST /v1/objects/{collection}/bulk/subscriptions/add`

**Rate limit tier:** 1

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.

#### Request body

A request to upsert subscriptions for many groups of 1 subscribed-to object, N subscriber recipients.

##### Example

```json
{
  "subscriptions": [
    {
      "id": "project-1",
      "properties": null,
      "recipients": [
        {
          "id": "user_1"
        }
      ]
    }
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Bulk delete objects

Bulk deletes objects from the specified collection.

#### Endpoint

`POST /v1/objects/{collection}/bulk/delete`

**Rate limit tier:** 1

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.

#### Request body

Request body for bulk deleting objects.

##### Example

```json
{
  "object_ids": [
    "obj_123",
    "obj_456",
    "obj_789"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Bulk delete subscriptions

Delete subscriptions for many objects in a single collection type. If a subscription for an object in the collection doesn't exist, it will be skipped.

#### Endpoint

`POST /v1/objects/{collection}/bulk/subscriptions/delete`

**Rate limit tier:** 1

#### Path parameters

- **collection** (string) *required* - The collection this object belongs to.

#### Request body

A request to delete subscriptions for many groups of 1 subscribed-to object, N subscriber recipients.

##### Example

```json
{
  "subscriptions": [
    {
      "id": "subscribed-to-object-1",
      "recipients": [
        {
          "collection": "projects",
          "id": "subscriber-project-1"
        },
        "subscriber-user-1"
      ]
    },
    {
      "id": "subscribed-to-object-2",
      "recipients": [
        "subscriber-user-2"
      ]
    }
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Object

A custom [Object](/concepts/objects) entity which belongs to a collection.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **collection** (string) *required* - The collection this object belongs to.
- **created_at** (string) - Timestamp when the resource was created.
- **id** (string) *required* - Unique identifier for the object.
- **properties** (object) - The custom properties associated with the object.
- **updated_at** (string) *required* - The timestamp when the resource was last updated.

#### Example

```json
{
  "__typename": "Object",
  "collection": "assets",
  "created_at": null,
  "id": "specimen_25",
  "properties": {
    "classification": "Theropod",
    "config": {
      "biz": "baz",
      "foo": "bar"
    },
    "name": "Velociraptor",
    "status": "contained"
  },
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### InlineIdentifyObjectRequest

A custom [Object](/concepts/objects) entity which belongs to a collection.

#### Attributes

- **channel_data** (unknown) - An optional set of [channel data](/managing-recipients/setting-channel-data) for the object. This is a list of `ChannelData` objects.
- **collection** (string) *required* - The collection this object belongs to.
- **created_at** (string) - Timestamp when the resource was created.
- **id** (string) *required* - Unique identifier for the object.
- **name** (string) - An optional name for the object.
- **preferences** (unknown) - An optional set of [preferences](/concepts/preferences) for the object.

#### Example

```json
{
  "collection": "projects",
  "id": "project_1",
  "name": "My project"
}
```

## Tenants

A [Tenant](/concepts/tenants) a grouping with configurable settings that can be applied to a workflow when it's triggered in order to override account-level settings such as branding. Use tenants when sending a notification to user(s) that you want to configure specific brand elements for, such as a separate organization logo.

### Available endpoints

- **DELETE** `/v1/tenants/{id}` - Delete a tenant
- **GET** `/v1/tenants/{id}` - Get a tenant
- **PUT** `/v1/tenants/{id}` - Set a tenant
- **GET** `/v1/tenants` - List tenants

### Delete a tenant

Delete a tenant and all associated data. This operation cannot be undone.

#### Endpoint

`DELETE /v1/tenants/{id}`

**Rate limit tier:** 2

#### Path parameters

- **id** (string) *required* - The unique identifier for the tenant.

#### Responses

##### 204

No Content

### Get a tenant

Get a tenant by ID.

#### Endpoint

`GET /v1/tenants/{id}`

**Rate limit tier:** 4

#### Path parameters

- **id** (string) *required* - The unique identifier for the tenant.

#### Query parameters

- **resolve_full_preference_settings** (boolean) - When true, merges environment-level default preferences into the tenant's `settings.preference_set` field before returning the response. Defaults to false.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Tenant",
  "id": "tenant_jp123",
  "name": "Jurassic Park",
  "settings": {
    "branding": {
      "dark_icon_url": "https://example.com/trex_silhouette_icon_dark.png",
      "dark_logo_url": "https://example.com/amber_fossil_logo_dark.png",
      "dark_primary_color": "#FFFFFF",
      "dark_primary_color_contrast": "#000000",
      "icon_url": "https://example.com/trex_silhouette_icon.png",
      "logo_url": "https://example.com/amber_fossil_logo.png",
      "primary_color": "#DF1A22",
      "primary_color_contrast": "#FFDE00"
    },
    "preference_set": {
      "categories": {
        "safety": {
          "channel_types": {
            "email": true,
            "push": true
          }
        }
      },
      "channel_types": {
        "email": true,
        "in_app_feed": true,
        "push": true
      },
      "id": "default",
      "workflows": {
        "park_alert": {
          "channel_types": {
            "email": true,
            "push": true
          }
        }
      }
    }
  }
}
```

### Set a tenant

Sets a tenant within an environment, performing an upsert operation. Any existing properties will be merged with the incoming properties.

#### Endpoint

`PUT /v1/tenants/{id}`

**Rate limit tier:** 3

#### Path parameters

- **id** (string) *required* - The unique identifier for the tenant.

#### Query parameters

- **resolve_full_preference_settings** (boolean) - When true, merges environment-level default preferences into the tenant's `settings.preference_set` field before returning the response. Defaults to false.

#### Request body

A tenant to be set in the system. You can supply any additional properties on the tenant object.

##### Example

```json
{
  "name": "Jurassic Park",
  "settings": {
    "branding": {
      "icon_url": "https://example.com/trex_silhouette_icon.png",
      "logo_url": "https://example.com/amber_fossil_logo.png",
      "primary_color": "#DF1A22",
      "primary_color_contrast": "#FFDE00"
    }
  }
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "Tenant",
  "created_at": "1993-05-24T08:30:00Z",
  "id": "ingen_isla_nublar",
  "name": "Jurassic Park",
  "settings": {
    "branding": {
      "icon_url": "https://example.com/trex_silhouette_icon.png",
      "logo_url": "https://example.com/amber_fossil_logo.png",
      "primary_color": "#DF1A22",
      "primary_color_contrast": "#FFDE00"
    }
  },
  "updated_at": "1993-06-11T15:45:00Z"
}
```

### List tenants

List tenants for the current environment.

#### Endpoint

`GET /v1/tenants`

**Rate limit tier:** 4

#### Query parameters

- **tenant_id** (string) - Filter tenants by ID.
- **name** (string) - Filter tenants by name.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Tenant",
      "id": "tenant_jp123",
      "name": "Jurassic Park",
      "settings": {
        "branding": {
          "dark_icon_url": "https://example.com/trex_silhouette_icon_dark.png",
          "dark_logo_url": "https://example.com/amber_fossil_logo_dark.png",
          "dark_primary_color": "#FFFFFF",
          "dark_primary_color_contrast": "#000000",
          "icon_url": "https://example.com/trex_silhouette_icon.png",
          "logo_url": "https://example.com/amber_fossil_logo.png",
          "primary_color": "#DF1A22",
          "primary_color_contrast": "#FFDE00"
        },
        "preference_set": {
          "categories": {
            "safety": {
              "channel_types": {
                "email": true,
                "push": true
              }
            }
          },
          "channel_types": {
            "email": true,
            "in_app_feed": true,
            "push": true
          },
          "id": "default",
          "workflows": {
            "park_alert": {
              "channel_types": {
                "email": true,
                "push": true
              }
            }
          }
        }
      }
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Bulk operations

Bulk operations available for tenants. These endpoints return a BulkOperation that executes the job asynchronously. Progress can be tracked via the [Bulk operations API](/api-reference/bulk_operations).

#### Available endpoints

- **POST** `/v1/tenants/bulk/delete` - Bulk delete tenants
- **POST** `/v1/tenants/bulk/set` - Bulk set tenants

### Bulk delete tenants

Delete up to 1,000 tenants at a time in a single operation. This operation cannot be undone.

#### Endpoint

`POST /v1/tenants/bulk/delete`

**Rate limit tier:** 1

#### Query parameters

- **tenant_ids** (array) *required* - The IDs of the tenants to delete.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Bulk set tenants

Set or update up to 1,000 tenants in a single operation.

#### Endpoint

`POST /v1/tenants/bulk/set`

**Rate limit tier:** 1

#### Request body

A request to set tenants in bulk.

##### Example

```json
{
  "tenants": [
    {
      "id": "tenant_1",
      "name": "Acme Corp, Inc."
    }
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Tenant

A tenant entity.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **id** (string) *required* - The unique identifier for the tenant.
- **name** (string) - An optional name for the tenant.
- **settings** (object) - The settings for the tenant. Includes branding and preference set.

#### Example

```json
{
  "__typename": "Tenant",
  "id": "tenant_jp123",
  "name": "Jurassic Park",
  "settings": {
    "branding": {
      "dark_icon_url": "https://example.com/trex_silhouette_icon_dark.png",
      "dark_logo_url": "https://example.com/amber_fossil_logo_dark.png",
      "dark_primary_color": "#FFFFFF",
      "dark_primary_color_contrast": "#000000",
      "icon_url": "https://example.com/trex_silhouette_icon.png",
      "logo_url": "https://example.com/amber_fossil_logo.png",
      "primary_color": "#DF1A22",
      "primary_color_contrast": "#FFDE00"
    },
    "preference_set": {
      "categories": {
        "safety": {
          "channel_types": {
            "email": true,
            "push": true
          }
        }
      },
      "channel_types": {
        "email": true,
        "in_app_feed": true,
        "push": true
      },
      "id": "default",
      "workflows": {
        "park_alert": {
          "channel_types": {
            "email": true,
            "push": true
          }
        }
      }
    }
  }
}
```

### TenantRequest

A tenant to be set in the system. You can supply any additional properties on the tenant object.

#### Attributes

- **channel_data** (unknown) - The channel data for the tenant.
- **id** (string) *required* - The unique identifier for the tenant.
- **name** (string) - An optional name for the tenant.
- **preferences** (unknown) - The preferences for the tenant.
- **settings** (object) - The settings for the tenant. Includes branding and preference set.

#### Example

```json
{
  "id": "tenant_123",
  "name": "ACME Corp, Inc.",
  "settings": {
    "branding": {
      "dark_icon_url": "https://example.com/icon_dark.png",
      "dark_logo_url": "https://example.com/logo_dark.png",
      "dark_primary_color": "#FFFFFF",
      "dark_primary_color_contrast": "#000000",
      "icon_url": "https://example.com/icon.png",
      "logo_url": "https://example.com/logo.png",
      "primary_color": "#000000",
      "primary_color_contrast": "#FFFFFF"
    }
  }
}
```

### InlineTenantRequest

An request to set a tenant inline.

#### Attributes

#### Example

```json
{
  "id": "tenant_1",
  "name": "Acme Corp, Inc."
}
```

## Schedules

A [Schedule](/concepts/schedules) allows you to automatically trigger a workflow at a given time for one or more recipients. You can think of a schedule as a managed, recipient-timezone-aware cron job that Knock will run on your behalf.

### Available endpoints

- **POST** `/v1/schedules` - Create schedules
- **GET** `/v1/schedules` - List schedules
- **PUT** `/v1/schedules` - Update schedules
- **DELETE** `/v1/schedules` - Delete schedules

### Create schedules

Creates one or more schedules for a workflow with the specified recipients, timing, and data. Schedules can be one-time or recurring. This endpoint also handles [inline identifications](/managing-recipients/identifying-recipients#inline-identifying-recipients) for the `actor`, `recipient`, and `tenant` fields.

#### Endpoint

`POST /v1/schedules`

**Rate limit tier:** 3

#### Request body

A request to create a schedule.

##### Example

```json
{
  "data": {
    "key": "value"
  },
  "ending_at": null,
  "recipients": [
    "user_123"
  ],
  "repeats": [
    {
      "__typename": "ScheduleRepeat",
      "day_of_month": null,
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri",
        "sat",
        "sun"
      ],
      "frequency": "daily",
      "hours": null,
      "interval": 1,
      "minutes": null
    }
  ],
  "scheduled_at": null,
  "tenant": "acme_corp",
  "workflow": "comment-created"
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Schedule",
    "actor": null,
    "data": null,
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "inserted_at": "2021-01-01T00:00:00Z",
    "last_occurrence_at": null,
    "next_occurrence_at": null,
    "recipient": {
      "__typename": "User",
      "avatar": null,
      "created_at": null,
      "email": "jane@ingen.net",
      "id": "jane",
      "name": "Jane Doe",
      "phone_number": null,
      "timezone": null,
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "repeats": [
      {
        "__typename": "ScheduleRepeat",
        "day_of_month": null,
        "days": [
          "mon",
          "tue",
          "wed",
          "thu",
          "fri",
          "sat",
          "sun"
        ],
        "frequency": "daily",
        "hours": null,
        "interval": 1,
        "minutes": null
      }
    ],
    "tenant": null,
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "workflow_123"
  }
]
```

### List schedules

Returns a paginated list of schedules for the current environment, filtered by workflow and optionally by recipients and tenant.

#### Endpoint

`GET /v1/schedules`

**Rate limit tier:** 4

#### Query parameters

- **workflow** (string) *required* - Filter by workflow key.
- **recipients[]** (array) - Filter by recipient references.
- **tenant** (string) - Filter by tenant ID.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) - The number of items per page (defaults to 50).

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "Schedule",
      "actor": null,
      "data": null,
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "inserted_at": "2021-01-01T00:00:00Z",
      "last_occurrence_at": null,
      "next_occurrence_at": null,
      "recipient": {
        "__typename": "User",
        "avatar": null,
        "created_at": null,
        "email": "jane@ingen.net",
        "id": "jane",
        "name": "Jane Doe",
        "phone_number": null,
        "timezone": null,
        "updated_at": "2024-05-22T12:00:00Z"
      },
      "repeats": [
        {
          "__typename": "ScheduleRepeat",
          "day_of_month": null,
          "days": [
            "mon",
            "tue",
            "wed",
            "thu",
            "fri",
            "sat",
            "sun"
          ],
          "frequency": "daily",
          "hours": null,
          "interval": 1,
          "minutes": null
        }
      ],
      "tenant": null,
      "updated_at": "2021-01-01T00:00:00Z",
      "workflow": "workflow_123"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Update schedules

Updates one or more existing schedules with new timing, data, or other properties. All specified schedule IDs will be updated with the same values. This endpoint also handles [inline identifications](/managing-recipients/identifying-recipients#inline-identifying-recipients) for the `actor`, `recipient`, and `tenant` fields.

#### Endpoint

`PUT /v1/schedules`

**Rate limit tier:** 3

#### Request body

A request to update a schedule.

##### Example

```json
{
  "actor": null,
  "data": {
    "key": "value"
  },
  "ending_at": null,
  "repeats": [
    {
      "__typename": "ScheduleRepeat",
      "day_of_month": null,
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri",
        "sat",
        "sun"
      ],
      "frequency": "daily",
      "hours": null,
      "interval": 1,
      "minutes": null
    }
  ],
  "schedule_ids": [
    "123e4567-e89b-12d3-a456-426614174000"
  ],
  "scheduled_at": null,
  "tenant": "acme_corp"
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Schedule",
    "actor": null,
    "data": null,
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "inserted_at": "2021-01-01T00:00:00Z",
    "last_occurrence_at": null,
    "next_occurrence_at": null,
    "recipient": {
      "__typename": "User",
      "avatar": null,
      "created_at": null,
      "email": "jane@ingen.net",
      "id": "jane",
      "name": "Jane Doe",
      "phone_number": null,
      "timezone": null,
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "repeats": [
      {
        "__typename": "ScheduleRepeat",
        "day_of_month": null,
        "days": [
          "mon",
          "tue",
          "wed",
          "thu",
          "fri",
          "sat",
          "sun"
        ],
        "frequency": "daily",
        "hours": null,
        "interval": 1,
        "minutes": null
      }
    ],
    "tenant": null,
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "workflow_123"
  }
]
```

### Delete schedules

Permanently deletes one or more schedules identified by the provided schedule IDs. This operation cannot be undone.

#### Endpoint

`DELETE /v1/schedules`

**Rate limit tier:** 3

#### Request body

A request to delete a schedule.

##### Example

```json
{
  "schedule_ids": [
    "123e4567-e89b-12d3-a456-426614174000"
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
[
  {
    "__typename": "Schedule",
    "actor": null,
    "data": null,
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "inserted_at": "2021-01-01T00:00:00Z",
    "last_occurrence_at": null,
    "next_occurrence_at": null,
    "recipient": {
      "__typename": "User",
      "avatar": null,
      "created_at": null,
      "email": "jane@ingen.net",
      "id": "jane",
      "name": "Jane Doe",
      "phone_number": null,
      "timezone": null,
      "updated_at": "2024-05-22T12:00:00Z"
    },
    "repeats": [
      {
        "__typename": "ScheduleRepeat",
        "day_of_month": null,
        "days": [
          "mon",
          "tue",
          "wed",
          "thu",
          "fri",
          "sat",
          "sun"
        ],
        "frequency": "daily",
        "hours": null,
        "interval": 1,
        "minutes": null
      }
    ],
    "tenant": null,
    "updated_at": "2021-01-01T00:00:00Z",
    "workflow": "workflow_123"
  }
]
```

### Bulk schedules

Bulk operations available for schedules.

#### Available endpoints

- **POST** `/v1/schedules/bulk/create` - Create schedules in bulk

### Create schedules in bulk

Bulk creates up to 1,000 schedules at a time. This endpoint also handles [inline identifications](/managing-recipients/identifying-recipients#inline-identifying-recipients) for the `actor`, `recipient`, and `tenant` fields.

#### Endpoint

`POST /v1/schedules/bulk/create`

**Rate limit tier:** 1

#### Request body

A request to bulk create schedules. Accepts a list of schedules to create. Each schedule must have a single recipient. The recipients do not have to be unique.

##### Example

```json
{
  "schedules": [
    {
      "data": {
        "key": "value"
      },
      "ending_at": null,
      "recipient": "dnedry",
      "repeats": [
        {
          "__typename": "ScheduleRepeat",
          "day_of_month": null,
          "days": [
            "mon",
            "tue",
            "wed",
            "thu",
            "fri",
            "sat",
            "sun"
          ],
          "frequency": "daily",
          "hours": null,
          "interval": 1,
          "minutes": null
        }
      ],
      "scheduled_at": null,
      "tenant": "acme_corp",
      "workflow": "comment-created"
    },
    {
      "data": {
        "key": "value"
      },
      "ending_at": null,
      "recipient": "esattler",
      "repeats": [
        {
          "__typename": "ScheduleRepeat",
          "day_of_month": null,
          "days": [
            "mon",
            "tue",
            "wed",
            "thu",
            "fri",
            "sat",
            "sun"
          ],
          "frequency": "daily",
          "hours": null,
          "interval": 1,
          "minutes": null
        }
      ],
      "scheduled_at": null,
      "tenant": "acme_corp",
      "workflow": "comment-created"
    }
  ]
}
```

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### Schedule

A schedule represents a recurring workflow execution.

#### Attributes

- **__typename** (string) - The typename of the schema.
- **actor** (unknown) - A map of properties describing a user or an object to identify in Knock and mark as who or what performed the action.
- **data** (object) - An optional map of data to pass into the workflow execution. There is a 10MB limit on the size of the full `data` payload. Any individual string value greater than 1024 bytes in length will be [truncated](/developer-tools/api-logs#log-truncation) in your logs.
- **id** (string) *required* - Unique identifier for the schedule.
- **inserted_at** (string) *required* - Timestamp when the resource was created.
- **last_occurrence_at** (string) - The last occurrence of the schedule.
- **next_occurrence_at** (string) - The next occurrence of the schedule.
- **recipient** (object) *required* - A recipient of a notification, which is either a user or an object.
- **repeats** (array) *required* - The repeat rule for the schedule.
- **tenant** (string) - The tenant to trigger the workflow for. Triggering with a tenant will use any tenant-level overrides associated with the tenant object, and all messages produced from workflow runs will be tagged with the tenant.
- **updated_at** (string) *required* - The timestamp when the resource was last updated.
- **workflow** (string) *required* - The workflow the schedule is applied to.

#### Example

```json
{
  "__typename": "Schedule",
  "actor": null,
  "data": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2021-01-01T00:00:00Z",
  "last_occurrence_at": null,
  "next_occurrence_at": null,
  "recipient": {
    "__typename": "User",
    "avatar": null,
    "created_at": null,
    "email": "jane@ingen.net",
    "id": "jane",
    "name": "Jane Doe",
    "phone_number": null,
    "timezone": null,
    "updated_at": "2024-05-22T12:00:00Z"
  },
  "repeats": [
    {
      "__typename": "ScheduleRepeat",
      "day_of_month": null,
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri",
        "sat",
        "sun"
      ],
      "frequency": "daily",
      "hours": null,
      "interval": 1,
      "minutes": null
    }
  ],
  "tenant": null,
  "updated_at": "2021-01-01T00:00:00Z",
  "workflow": "workflow_123"
}
```

### ScheduleRepeatRule

The repeat rule for the schedule.

#### Attributes

- **__typename** (string) - The typename of the schema.
- **day_of_month** (integer) - The day of the month to repeat the schedule.
- **days** (array) - The days of the week to repeat the schedule.
- **frequency** (string) *required* - The frequency of the schedule.
- **hours** (integer) - The hour of the day to repeat the schedule.
- **interval** (integer) - The interval of the schedule.
- **minutes** (integer) - The minute of the hour to repeat the schedule.

#### Example

```json
{
  "__typename": "ScheduleRepeat",
  "day_of_month": null,
  "days": [
    "mon",
    "tue",
    "wed",
    "thu",
    "fri",
    "sat",
    "sun"
  ],
  "frequency": "daily",
  "hours": null,
  "interval": 1,
  "minutes": null
}
```

## Audiences

An [Audience](/concepts/audiences) represents a user segment. Use the Audiences API to sync user segments from your data warehouse to Knock. Audiences can be used to target messages or orchestrate workflows via branch and step conditions. They can also be used as the recipient of a [Broadcast](/concepts/broadcasts).

### Available endpoints

- **POST** `/v1/audiences/{key}/members` - Add members
- **GET** `/v1/audiences/{key}/members` - List members
- **DELETE** `/v1/audiences/{key}/members` - Remove members

### Add members

Adds one or more members to the specified audience.

#### Endpoint

`POST /v1/audiences/{key}/members`

**Rate limit tier:** 3

#### Path parameters

- **key** (string) *required* - The key of the audience.

#### Query parameters

- **create_audience** (boolean) - Create the audience if it does not exist.

#### Request body

A request to add a list of audience members.

##### Example

```json
{
  "members": [
    {
      "tenant": "ingen_isla_nublar",
      "user": {
        "email": "ellie@ingen.net",
        "id": "dr_sattler",
        "name": "Dr. Ellie Sattler"
      }
    }
  ]
}
```

#### Responses

##### 204

No Content

### List members

Returns a paginated list of members for the specified audience.

#### Endpoint

`GET /v1/audiences/{key}/members`

**Rate limit tier:** 4

#### Path parameters

- **key** (string) *required* - The key of the audience.

#### Responses

##### 200

OK

###### Example

```json
{
  "entries": [
    {
      "__typename": "AudienceMember",
      "added_at": "1993-06-10T14:30:00Z",
      "tenant": "ingen_isla_nublar",
      "user": {
        "__typename": "User",
        "created_at": null,
        "email": "alan.grant@dig.site.mt",
        "id": "dr_grant",
        "name": "Dr. Alan Grant",
        "updated_at": "1993-06-09T08:15:00Z"
      },
      "user_id": "dr_grant"
    }
  ],
  "page_info": {
    "__typename": "PageInfo",
    "after": null,
    "before": null,
    "page_size": 25
  }
}
```

### Remove members

Removes one or more members from the specified audience.

#### Endpoint

`DELETE /v1/audiences/{key}/members`

**Rate limit tier:** 3

#### Path parameters

- **key** (string) *required* - The key of the audience.

#### Request body

A request to remove a list of audience members.

##### Example

```json
{
  "members": [
    {
      "tenant": "ingen_isla_nublar",
      "user": {
        "email": "ellie@ingen.net",
        "id": "dr_sattler",
        "name": "Dr. Ellie Sattler"
      }
    }
  ]
}
```

#### Responses

##### 204

No Content

### AudienceMember

An audience member.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **added_at** (string) *required* - Timestamp when the resource was created.
- **tenant** (string) - The unique identifier for the tenant.
- **user** (object) *required* - A [User](/concepts/users) represents an individual in your system who can receive notifications through Knock. Users are the most common recipients of notifications and are always referenced by your internal identifier.
- **user_id** (string) *required* - The unique identifier of the user.

#### Example

```json
{
  "__typename": "AudienceMember",
  "added_at": "1993-06-10T14:30:00Z",
  "tenant": "ingen_isla_nublar",
  "user": {
    "__typename": "User",
    "created_at": null,
    "email": "alan.grant@dig.site.mt",
    "id": "dr_grant",
    "name": "Dr. Alan Grant",
    "updated_at": "1993-06-09T08:15:00Z"
  },
  "user_id": "dr_grant"
}
```

### AudienceMemberRequest

An audience member.

#### Attributes

- **tenant** (string) - The unique identifier for the tenant.
- **user** (unknown) *required* - A user object. At minimum must contain an `id` property.

#### Example

```json
{
  "tenant": "ingen_isla_nublar",
  "user": {
    "email": "ellie@ingen.net",
    "id": "dr_sattler",
    "name": "Dr. Ellie Sattler"
  }
}
```

## Bulk operations

A Bulk Operation is a set of changes applied across 0 or more records triggered via a call to the Knock API and performed asynchronously. The BulkOperation record represents the state of the operation, including recording the number of rows that have been modified during the operation.

Please note here: the `estimated_total_rows` field may have a different value to the `processed_rows` field due to the asynchronous nature of the operation.

### Available endpoints

- **GET** `/v1/bulk_operations/{id}` - Get bulk operation

### Get bulk operation

Retrieves a bulk operation (if it exists) and displays the current state of it.

#### Endpoint

`GET /v1/bulk_operations/{id}`

**Rate limit tier:** 4

#### Path parameters

- **id** (string) *required* - The ID of the bulk operation to retrieve.

#### Responses

##### 200

OK

###### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### BulkOperation

A bulk operation entity.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **completed_at** (string) - Timestamp when the bulk operation was completed.
- **error_count** (integer) - The number of failed operations.
- **error_items** (array) - A list of items that failed to be processed.
- **estimated_total_rows** (integer) *required* - The estimated total number of rows to process.
- **failed_at** (string) - Timestamp when the bulk operation failed.
- **id** (string) *required* - Unique identifier for the bulk operation.
- **inserted_at** (string) *required* - Timestamp when the resource was created.
- **name** (string) *required* - The name of the bulk operation.
- **processed_rows** (integer) *required* - The number of rows processed so far.
- **progress_path** (string) - The URI to the bulk operation's progress.
- **started_at** (string) - Timestamp when the bulk operation was started.
- **status** (string) *required* - The status of the bulk operation.
- **success_count** (integer) *required* - The number of successful operations.
- **updated_at** (string) *required* - The timestamp when the resource was last updated.

#### Example

```json
{
  "__typename": "BulkOperation",
  "completed_at": null,
  "error_count": 0,
  "error_items": [],
  "estimated_total_rows": 1000,
  "failed_at": null,
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "inserted_at": "2024-05-22T12:00:00Z",
  "name": "Bulk operation name",
  "processed_rows": 0,
  "progress_path": "https://api.switchboard.com/v1/bulk_operations/123e4567-e89b-12d3-a456-426614174000",
  "started_at": null,
  "status": "processing",
  "success_count": 0,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

## Providers

A Provider is a channel-specific configuration that determines how a message is delivered to a recipient.

### Slack

A Slack provider is a channel-specific configuration that determines how a message is delivered to a recipient via Slack.

#### Available endpoints

- **GET** `/v1/providers/slack/{channel_id}/channels` - List channels
- **GET** `/v1/providers/slack/{channel_id}/auth_check` - Check auth
- **PUT** `/v1/providers/slack/{channel_id}/revoke_access` - Revoke access

### List channels

List Slack channels for a Slack workspace.

#### Endpoint

`GET /v1/providers/slack/{channel_id}/channels`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Slack channel to get channels for.

#### Query parameters

- **access_token_object** (string) *required* - A JSON encoded string containing the access token object reference.
- **query_options.cursor** (string) - Paginate through collections of data by setting the cursor parameter to a next_cursor attribute returned by a previous request's response_metadata. Default value fetches the first "page" of the collection.
- **query_options.limit** (integer) - The maximum number of channels to return. Defaults to 200.
- **query_options.exclude_archived** (boolean) - Set to true to exclude archived channels from the list. Defaults to `true` when not explicitly provided.
- **query_options.types** (string) - Mix and match channel types by providing a comma-separated list of any combination of public_channel, private_channel, mpim, im. Defaults to `"public_channel,private_channel"`. If the user's Slack ID is unavailable, this option is ignored and only public channels are returned.
- **query_options.team_id** (string) - Encoded team ID (T1234) to list channels in, required if org token is used.

#### Responses

##### 200

OK

###### Example

```json
{
  "next_cursor": null,
  "slack_channels": [
    {
      "context_team_id": "T01234567890",
      "id": "C01234567890",
      "is_im": false,
      "is_private": false,
      "name": "general"
    }
  ]
}
```

##### 403

Forbidden

###### Example

```json
{
  "code": "authorization",
  "message": "Access token not set.",
  "status": 403,
  "type": "authentication_error"
}
```

### Check auth

Check if a Slack channel is authenticated.

#### Endpoint

`GET /v1/providers/slack/{channel_id}/auth_check`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Slack channel to check.

#### Query parameters

- **access_token_object** (string) *required* - A JSON encoded string containing the access token object reference.

#### Responses

##### 200

OK

###### Example

```json
{
  "connection": {
    "ok": true
  }
}
```

### Revoke access

Revoke access for a Slack channel.

#### Endpoint

`PUT /v1/providers/slack/{channel_id}/revoke_access`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Slack channel to revoke access for.

#### Query parameters

- **access_token_object** (string) *required* - A JSON encoded string containing the access token object reference.

#### Responses

##### 200

OK

###### Example

```json
{
  "ok": "ok"
}
```

##### 403

Forbidden

###### Example

```json
{
  "code": "authorization",
  "message": "Access token not set.",
  "status": 403,
  "type": "authentication_error"
}
```

### Microsoft Teams

A Microsoft Teams provider is a channel-specific configuration that determines how a message is delivered to a recipient via Microsoft Teams.

#### Available endpoints

- **GET** `/v1/providers/ms-teams/{channel_id}/channels` - List channels
- **GET** `/v1/providers/ms-teams/{channel_id}/teams` - List teams
- **GET** `/v1/providers/ms-teams/{channel_id}/auth_check` - Check auth
- **PUT** `/v1/providers/ms-teams/{channel_id}/revoke_access` - Revoke access

### List channels

List the Microsoft Teams channels within a team. By default, archived and private channels are excluded from the results.

#### Endpoint

`GET /v1/providers/ms-teams/{channel_id}/channels`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Microsoft Teams channel to get channels for.

#### Query parameters

- **ms_teams_tenant_object** (string) *required* - A JSON encoded string containing the Microsoft Teams tenant object reference.
- **team_id** (string) *required* - Microsoft Teams team ID.
- **query_options.$filter** (string) - [OData param](https://learn.microsoft.com/en-us/graph/query-parameters) passed to the Microsoft Graph API to filter channels.
- **query_options.$select** (string) - [OData param](https://learn.microsoft.com/en-us/graph/query-parameters) passed to the Microsoft Graph API to select specific properties.

#### Responses

##### 200

OK

###### Example

```json
{
  "ms_teams_channels": [
    {
      "displayName": "General",
      "id": "channel-id-1"
    }
  ]
}
```

### List teams

Get a list of teams belonging to the Microsoft Entra tenant. By default, archived and private channels are excluded from the results.

#### Endpoint

`GET /v1/providers/ms-teams/{channel_id}/teams`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Microsoft Teams channel to get teams for.

#### Query parameters

- **ms_teams_tenant_object** (string) *required* - A JSON encoded string containing the Microsoft Teams tenant object reference.
- **query_options.$filter** (string) - [OData param](https://learn.microsoft.com/en-us/graph/query-parameters) passed to the Microsoft Graph API to filter teams.
- **query_options.$select** (string) - [OData param](https://learn.microsoft.com/en-us/graph/query-parameters) passed to the Microsoft Graph API to select fields on a team.
- **query_options.$top** (integer) - [OData param](https://learn.microsoft.com/en-us/graph/query-parameters) passed to the Microsoft Graph API to limit the number of teams returned.
- **query_options.$skiptoken** (string) - [OData param](https://learn.microsoft.com/en-us/graph/query-parameters) passed to the Microsoft Graph API to retrieve the next page of results.

#### Responses

##### 200

OK

###### Example

```json
{
  "ms_teams_teams": [
    {
      "displayName": "Engineering Team",
      "id": "team-id-1"
    }
  ],
  "skip_token": "token-for-next-page"
}
```

### Check auth

Check if a connection to Microsoft Teams has been authorized for a given Microsoft Teams tenant object.

#### Endpoint

`GET /v1/providers/ms-teams/{channel_id}/auth_check`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Microsoft Teams channel to check.

#### Query parameters

- **ms_teams_tenant_object** (string) *required* - A JSON encoded string containing the Microsoft Teams tenant object reference.

#### Responses

##### 200

OK

###### Example

```json
{
  "connection": {
    "ms_teams_tenant_id": "a Microsoft Teams tenant ID",
    "ok": true
  }
}
```

### Revoke access

Remove a Microsoft Entra tenant ID from a Microsoft Teams tenant object.

#### Endpoint

`PUT /v1/providers/ms-teams/{channel_id}/revoke_access`

**Rate limit tier:** 2

#### Path parameters

- **channel_id** (string) *required* - The ID of the Knock Microsoft Teams channel to revoke access for.

#### Query parameters

- **ms_teams_tenant_object** (string) *required* - A JSON encoded string containing the Microsoft Teams tenant object reference.

#### Responses

##### 200

OK

###### Example

```json
{
  "ok": "ok"
}
```

##### 403

Forbidden

###### Example

```json
{
  "code": "authorization",
  "message": "Access token not set.",
  "status": 403,
  "type": "authentication_error"
}
```

## Integrations

Integrations are used to connect your system to external services.

### Census

Census is a service that allows you to sync user segments from your data warehouse to Knock.

#### Available endpoints

- **POST** `/v1/integrations/census/custom-destination` - Process a Census RPC request

### Process a Census RPC request

Processes a Census custom destination RPC request.

#### Endpoint

`POST /v1/integrations/census/custom-destination`

**Rate limit tier:** 3

#### Request body

#### Responses

##### 200

OK

### Hightouch

Hightouch is a service that allows you to sync user segments from your data warehouse to Knock.

#### Available endpoints

- **POST** `/v1/integrations/hightouch/embedded-destination` - Process a Hightouch RPC request

### Process a Hightouch RPC request

Processes a Hightouch embedded destination RPC request.

#### Endpoint

`POST /v1/integrations/hightouch/embedded-destination`

**Rate limit tier:** 3

#### Request body

#### Responses

##### 200

OK

## Recipients

A [Recipient](/concepts/recipients) represents a person or a non-user entity from your system, represented in Knock. They are most commonly the recipient of a notification, but can also be used to denote an actor that a notification is sent on behalf of.

### Subscriptions

Subscriptions express the relationship between a [Recipient](/concepts/recipients) (the subscriber) and an [Object](/concepts/objects). Subscribers are notified when the object that they are subscribed to is a `recipient` on a workflow trigger request.

### Subscription

A subscription object.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **inserted_at** (string) *required* - Timestamp when the resource was created.
- **object** (object) *required* - A custom [Object](/concepts/objects) entity which belongs to a collection.
- **properties** (object) - The custom properties associated with the subscription relationship.
- **recipient** (object) *required* - A recipient of a notification, which is either a user or an object.
- **updated_at** (string) *required* - The timestamp when the resource was last updated.

#### Example

```json
{
  "__typename": "Subscription",
  "inserted_at": "2021-01-01T00:00:00Z",
  "object": {
    "__typename": "Object",
    "collection": "assets",
    "created_at": null,
    "id": "specimen_25",
    "properties": {
      "classification": "Theropod",
      "config": {
        "biz": "baz",
        "foo": "bar"
      },
      "name": "Velociraptor",
      "status": "contained"
    },
    "updated_at": "2024-05-22T12:00:00Z"
  },
  "recipient": {
    "__typename": "User",
    "avatar": null,
    "created_at": null,
    "email": "jane@ingen.net",
    "id": "jane",
    "name": "Jane Doe",
    "phone_number": null,
    "timezone": null,
    "updated_at": "2024-05-22T12:00:00Z"
  },
  "updated_at": "2021-01-01T00:00:00Z"
}
```

### Preferences

[Preferences](/concepts/preferences) determine whether a recipient should receive a particular type of notification. By default all preferences are opted in unless a preference explicitly opts the recipient out of the notification.

The preference set `:id` can be either `"default"` or a `tenant.id`. Learn more about [per-tenant preferences](/preferences/tenant-preferences).

### PreferenceSet

A preference set represents a specific set of notification preferences for a recipient. A recipient can have multiple preference sets.

#### Attributes

- **categories** (unknown) - An object where the key is the category and the values are the preference settings for that category.
- **channel_types** (unknown) - An object where the key is the channel type and the values are the preference settings for that channel type.
- **channels** (unknown) - An object where the key is the channel ID and the values are the preference settings for that channel ID.
- **commercial_subscribed** (unknown) - Whether the recipient is subscribed to commercial communications. When false, the recipient will not receive commercial workflow notifications. Can also be set to a settings object with conditions that are evaluated at notification send time.
- **id** (string) *required* - Unique identifier for the preference set.
- **workflows** (unknown) - An object where the key is the workflow key and the values are the preference settings for that workflow.

#### Example

```json
{
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true,
    "push": false,
    "sms": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    }
  },
  "commercial_subscribed": true,
  "id": "default",
  "workflows": null
}
```

### PreferenceSetRequest

A request to set a preference set for a recipient.

#### Attributes

- **__persistence_strategy__** (string) - Controls how the preference set is persisted. 'replace' will completely replace the preference set, 'merge' will merge with existing preferences.
- **categories** (unknown) - An object where the key is the category and the values are the preference settings for that category.
- **channel_types** (unknown) - An object where the key is the channel type and the values are the preference settings for that channel type.
- **channels** (unknown) - An object where the key is the channel ID and the values are the preference settings for that channel ID.
- **commercial_subscribed** (unknown) - Whether the recipient is subscribed to commercial communications. When false, the recipient will not receive commercial workflow notifications. Can also be set to a settings object with conditions that are evaluated at notification send time.
- **workflows** (unknown) - An object where the key is the workflow key and the values are the preference settings for that workflow.

#### Example

```json
{
  "__persistence_strategy__": "merge",
  "categories": {
    "marketing": false,
    "transactional": {
      "channel_types": {
        "email": false
      }
    }
  },
  "channel_types": {
    "email": true
  },
  "channels": {
    "2f641633-95d3-4555-9222-9f1eb7888a80": {
      "conditions": [
        {
          "argument": "US",
          "operator": "equal_to",
          "variable": "recipient.country_code"
        }
      ]
    },
    "aef6e715-df82-4ab6-b61e-b743e249f7b6": true
  },
  "commercial_subscribed": true,
  "workflows": {
    "dinosaurs-loose": {
      "channel_types": {
        "email": false
      }
    }
  }
}
```

### InlinePreferenceSetRequest

Inline set preferences for a recipient, where the key is the preference set id. Preferences that are set inline will be merged into any existing preferences rather than replacing them.

#### Attributes

#### Example

```json
{
  "default": {
    "categories": {
      "transactional": {
        "channel_types": {
          "email": false
        }
      }
    },
    "channel_types": {
      "email": true
    }
  }
}
```

### PreferenceSetChannelTypes

Channel type preferences.

#### Attributes

- **chat** (unknown) - Whether the channel type is enabled for the preference set.
- **email** (unknown) - Whether the channel type is enabled for the preference set.
- **http** (unknown) - Whether the channel type is enabled for the preference set.
- **in_app_feed** (unknown) - Whether the channel type is enabled for the preference set.
- **push** (unknown) - Whether the channel type is enabled for the preference set.
- **sms** (unknown) - Whether the channel type is enabled for the preference set.

#### Example

```json
{
  "email": true,
  "sms": {
    "conditions": [
      {
        "argument": "US",
        "operator": "equal_to",
        "variable": "recipient.country_code"
      }
    ]
  }
}
```

### PreferenceSetChannelTypeSetting

A set of settings for a channel type. Currently, this can only be a list of conditions to apply.

#### Attributes

- **conditions** (array) *required* - A list of conditions to apply to a channel type.

#### Example

```json
{
  "conditions": [
    {
      "argument": "US",
      "operator": "equal_to",
      "variable": "recipient.country_code"
    }
  ]
}
```

### PreferenceSetChannelSetting

A set of settings for a specific channel. Currently, this can only be a list of conditions to apply.

#### Attributes

- **conditions** (array) *required* - A list of conditions to apply to a specific channel.

#### Example

```json
{
  "conditions": [
    {
      "argument": "US",
      "operator": "equal_to",
      "variable": "recipient.country_code"
    }
  ]
}
```

### Channel data

[Channel data](/managing-recipients/setting-channel-data) is channel-specific information stored on a Knock [user](/api-reference/users) or [object](/api-reference/objects) that's needed to deliver a notification to an end provider.

For a push channel, this includes device-specific tokens that map the recipient to the device they use, as well as [device metadata](/integrations/push/device-metadata) for supported providers. For chat apps, such as Slack, this includes the access token used to send notifications to a customer's Slack channel.

The shape of the `data` payload varies depending on the channel type; you can learn more about channel data schemas [here](/send-notifications/setting-channel-data#provider-data-requirements).

### ChannelData

Channel data for a given channel type.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **channel_id** (string) *required* - The unique identifier for the channel.
- **data** (object) *required* - Channel data for a given channel type.
- **provider** (string) - The type of provider.

#### Example

```json
{
  "__typename": "ChannelData",
  "channel_id": "123e4567-e89b-12d3-a456-426614174000",
  "data": {
    "devices": [
      {
        "locale": null,
        "timezone": null,
        "token": "device_1"
      }
    ],
    "tokens": [
      "push_token_1"
    ]
  }
}
```

### ChannelDataRequest

A request to set channel data for a type of channel.

#### Attributes

- **data** (object) *required* - Channel data for a given channel type.

#### Example

```json
{
  "data": {
    "tokens": [
      "push_token_1"
    ]
  }
}
```

### PushChannelDataTokensOnly

Push channel data.

#### Attributes

- **tokens** (array) *required* - A list of push channel tokens.

#### Example

```json
{
  "tokens": [
    "push_token_1",
    "push_token_2"
  ]
}
```

### PushChannelDataDevicesOnly

Push channel data.

#### Attributes

- **devices** (array) *required* - A list of devices. Each device contains a token, and optionally a locale and timezone.

#### Example

```json
{
  "devices": [
    {
      "locale": "en-US",
      "timezone": "America/Los_Angeles",
      "token": "push_token_1"
    }
  ]
}
```

### SlackChannelData

Slack channel data.

#### Attributes

- **connections** (array) *required* - List of Slack channel connections.
- **token** (object) - A Slack connection token.

#### Example

```json
{
  "connections": [
    {
      "access_token": "xoxb-1234567890",
      "channel_id": "C01234567890",
      "channel_name": "team-alerts",
      "knock_tenant_id": "starfleet",
      "user_id": "U01234567890"
    }
  ],
  "token": {
    "access_token": "xoxb-1234567890"
  }
}
```

### AWSSNSPushChannelDataTargetARNsOnly

AWS SNS push channel data.

#### Attributes

- **target_arns** (array) *required* - A list of platform endpoint ARNs. See [Setting up an Amazon SNS platform endpoint for mobile notifications](https://docs.aws.amazon.com/sns/latest/dg/mobile-platform-endpoint.html).

#### Example

```json
{
  "target_arns": [
    "arn:aws:sns:us-west-2:123456789012:endpoint/GCM/gcmpushapp/5e3e9847-3183-3f18-a7e8-671c3a57d4b3"
  ]
}
```

### AWSSNSPushChannelDataDevicesOnly

AWS SNS push channel data.

#### Attributes

- **devices** (array) *required* - A list of devices. Each device contains a target_arn, and optionally a locale and timezone.

#### Example

```json
{
  "devices": [
    {
      "locale": "en-US",
      "target_arn": "arn:aws:sns:us-west-2:123456789012:endpoint/GCM/gcmpushapp/5e3e9847-3183-3f18-a7e8-671c3a57d4b3",
      "timezone": "America/Los_Angeles"
    }
  ]
}
```

### MsTeamsChannelData

Microsoft Teams channel data.

#### Attributes

- **connections** (array) *required* - List of Microsoft Teams connections.
- **ms_teams_tenant_id** (string) - Microsoft Teams tenant ID.

#### Example

```json
{
  "connections": [
    {
      "knock_tenant_id": "starfleet",
      "ms_teams_channel_id": "123e4567-e89b-12d3-a456-426614174000",
      "ms_teams_team_id": "123e4567-e89b-12d3-a456-426614174000",
      "ms_teams_tenant_id": null,
      "ms_teams_user_id": null
    }
  ],
  "ms_teams_tenant_id": null
}
```

### DiscordChannelData

Discord channel data.

#### Attributes

- **connections** (array) *required* - List of Discord channel connections.

#### Example

```json
{
  "connections": [
    {
      "channel_id": "123456789012345678",
      "knock_tenant_id": "starfleet"
    }
  ]
}
```

### OneSignalChannelDataPlayerIdsOnly

OneSignal channel data.

#### Attributes

- **player_ids** (array) *required* - A list of OneSignal player IDs.

#### Example

```json
{
  "player_ids": [
    "123e4567-e89b-12d3-a456-426614174000"
  ]
}
```

### InlineChannelDataRequest

A request to set channel data for a type of channel inline.

#### Attributes

#### Example

```json
{
  "97c5837d-c65c-4d54-aa39-080eeb81c69d": {
    "tokens": [
      "push_token_xxx"
    ]
  }
}
```

### Recipient

A recipient of a notification, which is either a user or an object.

#### Attributes

#### Example

```json
{
  "__typename": "User",
  "avatar": null,
  "created_at": null,
  "email": "jane@ingen.net",
  "id": "jane",
  "name": "Jane Doe",
  "phone_number": null,
  "timezone": null,
  "updated_at": "2024-05-22T12:00:00Z"
}
```

### RecipientRequest

Specifies a recipient in a request. This can either be a user identifier (string), an inline user request (object), or an inline object request, which is determined by the presence of a `collection` property.

#### Attributes

#### Example

```json
{
  "id": "user_1"
}
```

### RecipientReference

A reference to a recipient, either a user identifier (string) or an object reference (ID, collection).

#### Attributes

#### Example

```json
"user_123"
```

## Shared

Resources that are shared across the API.

### Condition

A condition to be evaluated.

#### Attributes

- **argument** (string) *required* - The argument value to compare against in the condition.
- **operator** (string) *required* - The operator to use in the condition evaluation.
- **variable** (string) *required* - The variable to be evaluated in the condition.

#### Example

```json
{
  "argument": "frog_genome",
  "operator": "contains",
  "variable": "specimen.dna_sequence"
}
```

### PageInfo

Pagination information for a list of resources.

#### Attributes

- **__typename** (string) *required* - The typename of the schema.
- **after** (string) - The cursor to fetch entries after.
- **before** (string) - The cursor to fetch entries before.
- **page_size** (integer) *required* - The number of items per page (defaults to 50).

#### Example

```json
{
  "__typename": "PageInfo",
  "after": null,
  "before": null,
  "page_size": 25
}
```

