> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.withpersona.com/2021-05-14/api-key-payload-filters/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.withpersona.com/_mcp/server. # Payload Filters > **Warning** > > #### Enterprise support > > This feature is restricted to customers on the Enterprise plan. Please reach out to your Account Team or [contact us](https://app.withpersona.com/dashboard/contact-us) if you are interested in enabling and setting up this feature. Payload filters restrict which records are visible through a given API key. When a payload filter is configured, the serialized [JSONAPI](https://jsonapi.org/) response for each record is matched against the filter: * **List endpoints**: Non-matching records are filtered out of the response. * **Single-resource endpoints**: A `403 Forbidden` status is returned if the record does not match the filter. If the payload filter is empty or not set, the API key behaves normally and all records are returned. ## Configuring a payload filter You can configure a payload filter for an API key in the [Dashboard](https://app.withpersona.com/dashboard/api-keys). Navigate to **API Keys**, click into a specific key, and select the **Payload filter** tab. The filter is a JSON object that you can edit directly. ![api-key-payload-filters](https://assets.withpersona.com/f_auto,q_auto/developer-docs/images/api-key-payload-filters.png) ## Examples > **Info** > > The examples below assume a key using kebab-case key inflection. ### Filtering by status To restrict an API key to only return completed Inquiries, you would set the following payload filter: **`json`** ```json json { "data": { "attributes": { "status": "completed" } } } ``` When listing Inquiries with this filter, only those with `"status": "completed"` in their serialized payload will appear. Retrieving a single Inquiry that is not completed will return a `403`. ### Filtering by relationship To restrict an API key to only return records associated with a specific Inquiry Template: **`json`** ```json json { "data": { "relationships": { "inquiry-template": { "data": { "id": "itmpl_abc123def456" } } } } } ``` ## Designing a payload filter Start by looking at the API response for the resource you want to filter. For example, retrieving an Inquiry (via [Retrieve an Inquiry](/api-reference/inquiries/retrieve-an-inquiry)) might return: **`json`** ```json json { "data": { "type": "inquiry", "id": "inq_XN8jxMoEhUeihzNypSaFKFfo", "attributes": { "status": "completed", "reference-id": null, "...": "...", "tags": ["INBOUND", "CAMPAIGN ABC"], "fields": { "address-country-code": { "type": "string", "value": "US" }, "...": "..." } }, "relationships": { "inquiry-template": { "data": { "type": "inquiry-template", "id": "itmpl_abc123def456" } }, "...": "..." } } } ``` Pick the value you want to filter on and keep only the keys in the path leading to that value. For example, to filter for Inquiries with country code `US`: **`json`** ```json json { "data": { "attributes": { "fields": { "address-country-code": { "value": "US" } } } } } ``` > **Info** > > Fields with `null` values cannot be matched by a payload filter. For example, filtering on `"address-country-code": { "value": "US" }` will only return records where that field is explicitly `"US"` — records where the field is `null` will not match. ## Matching against arrays To match against an array value in the payload, provide an array in the filter containing the elements you want to check for. All elements in the filter array must be present in the payload array for the record to match. Matching on Inquiries with a tag named "INBOUND": **`json`** ```json json { "data": { "attributes": { "tags": [ "INBOUND" ] } } } ``` Matching on Inquiries with both "INBOUND" and "CAMPAIGN ABC" tags: **`json`** ```json json { "data": { "attributes": { "tags": [ "INBOUND", "CAMPAIGN ABC" ] } } } ``` ## `$or` operator To allow for multiple criteria, use the `$or` operator. It can be used on a list of values or JSON object literals. Value example — match Inquiries with either of two Inquiry Templates: **`json`** ```json json { "data": { "relationships": { "inquiry-template": { "data": { "id": { "$or": [ "itmpl_abc123def456", "itmpl_ghi789jkl012" ] } } } } } } ``` Object example — match Inquiries that are either approved or completed: **`json`** ```json json { "data": { "attributes": { "$or": [ { "status": "approved" }, { "status": "completed" } ] } } } ``` ### `$or` on array fields When using `$or` to match against a field whose value is an array (like `tags`), the `$or` must be placed at the **parent level**, not directly on the array field. Each option should wrap the array field with the value(s) to match. This will **not** work — `$or` directly on an array field: **`json`** ```json json { "data": { "attributes": { "tags": { "$or": ["US 1", "CAN 1"] } } } } ``` Instead, place `$or` at the parent level with each option wrapping the array: **`json`** ```json json { "data": { "attributes": { "$or": [ { "tags": ["US 1"] }, { "tags": ["CAN 1"] } ] } } } ``` This also composes with other filters using AND semantics. For example, to match (tag "US 1" OR tag "CAN 1") AND (one of several templates): **`json`** ```json json { "data": { "attributes": { "$or": [ { "tags": ["US 1"] }, { "tags": ["CAN 1"] } ] }, "relationships": { "inquiry-template": { "data": { "id": { "$or": ["itmpl_aaa", "itmpl_bbb", "itmpl_ccc"] } } } } } } ``` > **Info** > > **Key rules for `$or`:** > > * `$or` on a **scalar field** (like `id`, `status`) works directly: `{ "id": { "$or": ["a", "b"] } }` > * `$or` on an **array field** (like `tags`) must be lifted to the parent object, with each option as `{ "field": ["value"] }` > * Multiple array values in a single option use AND semantics: `{ "tags": ["US 1", "CAN 1"] }` means "has both tags" > * Sibling keys at the same level are ANDed together > **Warning** > > #### Pagination > > Payload filtering is applied after pagination. This means a page may return fewer results than the requested `page[size]`, including empty pages with valid pagination cursors. Clients should continue paginating until no next cursor is returned. > Restrict which records are visible through an API key