---
title: "Create an audience"
method: POST
path: "/v1/audiences"
tags: ["Audiences"]
---

# Create an audience

`POST /v1/audiences`

Creates a saved audience from a name + filter set (`{ filters: [{ field, operator, value? }], logicalOperator: "and" | "or" }`). Returns `201` with the bare audience row.

## Headers

- `Idempotency-Key` string

## Request body

- AudiencesPostRequest
  - `name` string, required
  - `filters` object, required
    - `filters` object[], required
      - `field` string, required
      - `operator` 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'contains_any' | 'not_contains_any' | 'starts_with' | 'ends_with' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'is_true' | 'is_false' | 'in' | 'not_in' | 'is_empty' | 'not_exists' | 'is_not_empty' | 'exists' | 'is_set' | 'before' | 'after' | 'on_date', required
      - `value` unknown
      - `type` string — The field's value type — set `number`, `date`, or `boolean` for typed comparisons (dates are stored as epoch-ms, so a string `equals` on a date never matches). Omit for plain string fields.
    - `logicalOperator` 'and' | 'or', required

## Response `201`

Created.

- Audience
  - `audienceId` string, required
  - `audienceName` string, required
  - `filters` object, required
    - `filters` object[], required
      - `field` string, required
      - `operator` 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'contains_any' | 'not_contains_any' | 'starts_with' | 'ends_with' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'is_true' | 'is_false' | 'in' | 'not_in' | 'is_empty' | 'not_exists' | 'is_not_empty' | 'exists' | 'is_set' | 'before' | 'after' | 'on_date', required
      - `value` unknown
      - `type` string — The field's value type — set `number`, `date`, or `boolean` for typed comparisons (dates are stored as epoch-ms, so a string `equals` on a date never matches). Omit for plain string fields.
    - `logicalOperator` 'and' | 'or', required
  - `count` integer, required
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required

## Other responses

- `400` — The request body or query string was invalid (unknown key, wrong type, or missing required field). Strict schemas reject unknown keys — including `brandId`, which is always resolved from the API key.
- `401` — The API key was missing, invalid, or revoked.
- `403` — The caller does not have the required `audiences` permission.
- `409` — The same `Idempotency-Key` was reused with a different request body.
- `429` — The request hit the rolling rate limit window.
- `500` — Unexpected internal error.

---

[API](https://skmtc.net/brew/apis/brew-public-api-v1.md) · [All operations](https://skmtc.net/brew/apis/brew-public-api-v1/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/brew/brew-public-api-v1/revisions/db96cfedc6c5/schema)
