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 |
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.
| 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
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 |
{
"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. |