Guide
Counts and breakdowns
Count an audience for free and get Total, New to you and Emailable, the premium figure beside all records, up to three breakdowns, quality signals and a compliance summary. Small numbers are rounded for anonymous callers.
A count costs 0 credits, needs no account and returns in one request: contacts and companies together, three headline views, the premium figure beside all records, up to three breakdowns, and a content-addressed id that replays for 12 months. POST /v1/counts and count_audience take an audience, a level and up to 3 breakdown_by fields. The same audience gives the same number in the app, over REST and over MCP.
Run a count
Send an audience definition inline, or the aud_ id of a saved one.
{
"audience": { "schema": "mydatahub.audience/1", "dataset": "uk_contacts", "where": { "field": "company.sic_2007", "op": "in", "values": ["C"] } },
"level": "contact",
"breakdown_by": ["contact.job_level_rank"]
}level is contact (the default) or company. Contacts and companies come back together either way, so "12,840 contacts at 3,115 companies" is one call. See REST reference: Count an audience for every member.
Three views
Every count carries the same three headline views, and contacts is the Total.
| View | Member | What it counts |
|---|---|---|
| Total | contacts, companies | Every matching contact at an active company, with or without an email |
| New to you | new_to_you | Total, less records from your earlier orders and a connected CRM. null when signed out |
| Emailable | emailable | A named email scoring 70 or more at a corporate subscriber |
views repeats all three with contacts and companies each. It is the number to use before ordering, because records you already hold are never charged.
Premium and all records
Every count carries the premium figure beside the full one, so no number changes meaning without saying so.
| Member | What it counts |
|---|---|
premium | The contacts of all_records that are premium records. null when the dataset version carries no premium data, or withheld when the premium records are at a single company and the caller has no account |
all_records | The full figure: the audience with its top-level premium filters taken out. A premium filter inside any or not stays. The same as contacts when it has none |
premium_note | What premium means on this dataset version, or why premium is null |
views.premium and views.all_records give contacts and companies for each. Both are rounded for anonymous and trial callers exactly as every other figure is. Where the premium records are at a single company, an anonymous caller gets premium as null, with the reason in premium_note, and the rest of the count as usual.
A premium record is at an active company and has a LinkedIn profile. At launch it is a record in the premium export of a stated date, the dataset version's as-of date; later it will be a record validated within the last 12 months, from the validations feed. Filter on it with contact.premium, described in The audience definition.
A count runs your audience exactly as you send it, and the server never adds a premium filter. The app opens a new count with the premium chip on, and POST /v1/audiences/compile and compile_audience add contact.premium by default when the dataset version carries premium data, and say so in the readback. Remove the chip, or say "all records" in the brief, to count every record.
On a dataset version without premium data, premium is null, premium_note says so, and a contact.premium filter gets 422 validation-failed with the reason. It never counts 0 for want of data.
Defaults and toggles
The server applies four defaults and reports each one in defaults, with whether it was applied, the views it shapes and how many records it removed.
defaults id | Removes | Shapes |
|---|---|---|
active_companies | Dissolved and insolvent companies | Every view |
named_emails | Generic addresses such as info@ | Emailable |
corporate_subscribers | Sole traders and ordinary partnerships, which are individual subscribers under PECR | Emailable |
no_registered_phones | Numbers a screen found TPS or CTPS registered, when a phone is requested; numbers not screened stay in | Every view |
The numbers behind the toggles let a person or an agent see what a default costs before turning it off. Premium is not one of these defaults: it is a filter in the audience, shown with the figure beside it (see Premium and all records). Your own suppression lists are applied on top and reported per list in compliance_summary.suppressed_removed.
Breakdowns
Up to 3 fields in breakdown_by run as one grouped query. Each field returns its top 50 cells and an other bucket. Two or three fields also return a crosstab, capped at 5,000 cells and 200 KB.
{
"by": "contact.job_level_rank",
"cells": [
{ "value": "director", "contacts": 4120 }
]
}Hierarchical fields break down at one level: SIC by section and postcode by district. A seniority breakdown shows contacts with no known level last, as not_known labelled Level not known, with filter_value 0. A cell count is a whole number, the text under 10, or suppressed where a cell of 10 or more is hidden so that totals cannot be differenced.
Over MCP a cross-tab holds at most 200 cells, with truncated true when the cap cut it. Ask for fewer dimensions to see the rest.
Disclosure control
Small numbers can identify people, so what you see depends on who you are. This is the suppress-and-round practice used for UK statistical outputs, as in OpenSAFELY disclosure control.
| Caller | Counts | Breakdown cells |
|---|---|---|
| Anonymous | Counts under 100 rounded to the nearest 5 | Every cell rounded to the nearest 5, under 10 shown as under 10 |
| Free or trial account | The same as anonymous | The same as anonymous |
| Paid account | Exact | Exact, with under 10 shown as under 10 |
Every response that carries counts includes a disclosure object with its level (exact or rounded), rounded_to and secondary_suppression, so you can tell which figures you are reading. Single-company counts need an account and are logged.
A preview is withheld when the count is under 25. See Samples.
Quality signals
Each count shows how good the records are, with the date of measurement, so "verified" is never shown without a date.
| Member | What it measures |
|---|---|
quality.email_coverage_pct | Records with a named email as a share of the count |
quality.verified_90d_pct | Share of emails with a provider result of ok in the last 90 days |
quality.deliverability | Distribution: good is 70 to 100, risky is 40 to 69, poor is under 40 |
quality.avg_days_since_verification | Mean age of the latest verification result |
quality.phone_coverage_pct, quality.tps_ctps_screened_at | Phone coverage and the version's TPS and CTPS screen date, when a phone is requested |
Compliance summary
Every count returns compliance_summary beside the number, so you can reason about lawfulness before you spend. It holds the lawful basis (UK GDPR Article 6(1)(f) legitimate interests) and counts of corporate subscribers, individual subscribers excluded, TPS and CTPS numbers excluded, Article 14 notified and pending, and records removed per suppression list. See Compliance receipts.
Price estimate
estimate gives the credits an order of the whole count would need and the price in GBP ex VAT two ways: per_contact_scale, every credit at the scale, and cheapest, the cheapest real purchase at the scale or with credit packs. It is an estimate only. A machine quote is the price you pay.
Replay a count
GET /v1/counts/{id} returns the effective definition, the compiled plan (expanded terms, resolved centres, SIC codes behind a business class, suppression checksums), the pinned dataset_version and engine_rules_version, all three views with premium and all records, and the number on the current dataset. The ETag equals the id, so If-None-Match answers 304 without running the engine.
A count expires 12 months after it ran. See Versions and reproducibility.
An objection or erasure request reaches every count the same day through an overlay. A pinned re-run reports removed_since beside the original number.
Next steps
- Look at who is in the count with Samples.
- Price it with Quotes and orders.
- Save and share it with
POST /v1/audiences, then count byaud_id.