---
title: customers.audience | Doing Work API
description: Pick a customer audience by filters (tags, last job dates, kind of work, open quotes, money owed, maintenance plans, city or postal code, has email or phon
url: https://doingwork.work/docs/reference/customers-audience/
---

# customers.audience

Pick a customer audience by filters (tags, last job dates, kind of work, open quotes, money owed, maintenance plans, city or postal code, has email or phone) and get the counts and a page of matching customers. Read only: it sends nothing and changes nothing. Owner or office only; money filters need see_prices.

|  |  |
|---|---|
| Who | Agents can call this |
| REST | `POST /v1/customers/audience` |
| MCP tool | `customers_audience` |
| Writes | no |
| Area | [Shop](https://doingwork.work/docs/reference/#shop) |

## When to use it

Find the customers a message, campaign or call list is for: customers.audience takes filters (tags, when their last job was, kind of work done, an open quote, money owed, maintenance plan status and renewal dates, city or postal code, has an email or phone) and returns the counts and a page of matching customers. All filters must match.

## What to tell the owner

Tell them what you found in plain words. Don't read back raw fields.

## Input

| Field | Type | Required |
|---|---|---|
| `shop_id` | string (uuid) | yes |
| `tags_any` | array | no |
| `tags_all` | array | no |
| `tags_none` | array | no |
| `lead_sources` | array | no |
| `kind` | string (one of person, company) | no |
| `autopay` | boolean | no |
| `created_from` | string | no |
| `created_to` | string | no |
| `has_jobs` | boolean | no |
| `last_job_from` | string | no |
| `last_job_to` | string | no |
| `job_kinds` | array | no |
| `job_tags_any` | array | no |
| `job_summary_contains` | string | no |
| `jobs_from` | string | no |
| `jobs_to` | string | no |
| `has_open_quote` | boolean | no |
| `plan_status` | string (one of active, cancelled, none, any) | no |
| `plan_term_ends_from` | string | no |
| `plan_term_ends_to` | string | no |
| `cities` | array | no |
| `postal_codes` | array | no |
| `has_email` | boolean | no |
| `has_phone` | boolean | no |
| `owes_money` | boolean | no |
| `overdue` | boolean | no |
| `min_owed_minor` | integer | no |
| `min_spent_minor` | integer | no |
| `max_spent_minor` | integer | no |
| `include_archived` | boolean | no |
| `sort` | string (one of name, last_job_oldest, last_job_newest, created_newest) | no |
| `limit` | integer | no |
| `cursor` | string | no |

## Example

```http
POST https://doingwork.work/v1/customers/audience
content-type: application/json
Idempotency-Key: 3f1c...

{
  "shop_id": "00000000-0000-4000-8000-000000000000"
}
```

## Output

| Field | Type | Always there |
|---|---|---|
| `shop_id` | string (uuid) | yes |
| `time_zone` | string | yes |
| `currency` | string | yes |
| `sort` | string | yes |
| `counts` | object | yes |
| `counts.total` | integer | yes |
| `counts.with_email` | integer | yes |
| `counts.with_phone` | integer | yes |
| `counts.owing` | ['integer', 'null'] | yes |
| `counts.owed_minor` | ['integer', 'null'] | yes |
| `prices_hidden` | boolean | yes |
| `data` | array | yes |
| `data[].customer_id` | string (uuid) | yes |
| `data[].name` | string | yes |
| `data[].company_name` | ['string', 'null'] | yes |
| `data[].kind` | string | yes |
| `data[].email` | ['string', 'null'] | yes |
| `data[].phone` | ['string', 'null'] | yes |
| `data[].tags` | array | yes |
| `data[].lead_source` | ['string', 'null'] | yes |
| `data[].city` | ['string', 'null'] | yes |
| `data[].postal_code` | ['string', 'null'] | yes |
| `data[].jobs` | integer | yes |
| `data[].last_job_at` | ['string', 'null', ' ', '(', 'd', 'a', 't', 'e', '-', 't', 'i', 'm', 'e', ')'] | yes |
| `data[].open_quotes` | integer | yes |
| `data[].plan_status` | string | yes |
| `data[].owed_minor` | ['integer', 'null'] | yes |
| `data[].spent_minor` | ['integer', 'null'] | yes |
| `data[].archived` | boolean | yes |
| `data[].created_at` | string (date-time) | yes |
| `next_cursor` | ['string', 'null'] | yes |

```json
{
  "shop_id": "00000000-0000-4000-8000-000000000000",
  "time_zone": "...",
  "currency": "...",
  "sort": "...",
  "counts": {
    "total": 1,
    "with_email": 1,
    "with_phone": 1,
    "owing": "...",
    "owed_minor": "..."
  },
  "prices_hidden": true,
  "data": [
    {
      "customer_id": "00000000-0000-4000-8000-000000000000",
      "name": "Ruiz Plumbing",
      "company_name": "...",
      "kind": "...",
      "email": "owner@example.com",
      "phone": "...",
      "tags": [
        "..."
      ],
      "lead_source": "...",
      "city": "...",
      "postal_code": "83814",
      "jobs": 1,
      "last_job_at": "...",
      "open_quotes": 1,
      "plan_status": "...",
      "owed_minor": "...",
      "spent_minor": "...",
      "archived": true,
      "created_at": "..."
    }
  ],
  "next_cursor": "..."
}
```

## Errors

| Code | Status | What to do |
|---|---|---|
| `invalid_input`, `invalid_token`, `rate_limited` |  | Can happen on any call. See [errors](https://doingwork.work/docs/errors/). |
