UK B2B contact counts, quotes and lists, by Emailmovers
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Optional. A MyDataHub API key or agent key (mdh_live_...), made in the app under API keys. Without one, counts, breakdowns, previews and quotes still work, with rounded figures.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Deprecated: lists the filter categories. Use list_filters instead. It returns every field by name, such as company.employee_band, with its type, operators and value count. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
This tool takes no arguments.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http mydatahub https://mydatahub.emailmovers.com/mcp
Headers
Authorization (optional, not in the config above): Optional. A MyDataHub API key or agent key (mdh_live_...), made in the app under API keys. Without one, counts, breakdowns, previews and quotes still work, with rounded figures.Deprecated: lists the filter categories. Use list_filters instead. It returns every field by name, such as company.employee_band, with its type, operators and value count. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Deprecated: lists the values of one filter category by numeric id. Use search_filter_values instead. It takes the field name and search text and returns codes with contact and company counts. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Checks the suppression status of up to 1,000 delivered records by record id, as of now, and names the lists that suppress each. Use it before every send, because objections reach records after delivery. Free; it needs suppressions:read. Leave suppressed records out of the send, and call report_objection when someone objects. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| record_ids* | array |
{
"type": "object",
"required": [
"record_ids"
],
"properties": {
"record_ids": {
"type": "array",
"items": {
"type": "string",
"pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
],
"description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8."
},
"maxItems": 1000,
"minItems": 1
}
},
"description": "Records to check before a send.",
"additionalProperties": false
}Deprecated: clears the filters held in the server session. Use count_audience instead. There is nothing to clear: every count_audience call carries its own audience. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Compiles a plain English brief, such as 300 finance directors at law firms in Manchester, into an audience definition with a one-sentence readback, editable chips and any questions to answer first. Use it first for a request in words, read the readback to the user and settle the questions before counting. Words that match no filter come back in unrecognised, never guessed. Free and needs no account; pass the audience to count_audience next. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| brief* | string | A plain English brief, such as "300 finance directors at law firms in Manchester". |
| dataset | string | The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served. |
{
"type": "object",
"required": [
"brief"
],
"properties": {
"brief": {
"type": "string",
"maxLength": 2000,
"minLength": 3,
"description": "A plain English brief, such as \"300 finance directors at law firms in Manchester\"."
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
}
},
"description": "A brief to compile into an audience definition.",
"additionalProperties": false
}Counts UK contacts and companies matching an audience, inline or a saved aud_ id, and returns Total, New to you and Emailable, up to three breakdowns, quality, the compliance summary, a price estimate and a count id. Use it whenever a filter changes, and before preview_records or quote_order, which both take the count id. Free and needs no account; anonymous and trial callers see counts under 100 and breakdown cells rounded to the nearest 5 (disclosure says which), and exact small counts need a paid plan. It returns no contact details, and over MCP a cross-tab holds at most 200 cells (truncated true; GET /v1/counts/{id} has the rest). Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| level | string | contact (the default) or company. Contacts and companies come back together either way. |
| audience* | any | |
| breakdown_by | array | Up to three fields to break the count down by, each once, such as industry by seniority by region. Returns the top 50 cells per field plus other. |
{
"type": "object",
"$defs": {
"Filter": {
"oneOf": [
{
"$ref": "#/$defs/InFilter"
},
{
"$ref": "#/$defs/BetweenFilter"
},
{
"$ref": "#/$defs/GteFilter"
},
{
"$ref": "#/$defs/LteFilter"
},
{
"$ref": "#/$defs/MatchesFilter"
},
{
"$ref": "#/$defs/WithinRadiusFilter"
},
{
"$ref": "#/$defs/InListFilter"
},
{
"$ref": "#/$defs/SinceFilter"
}
],
"description": "One criterion: a field from GET /v1/catalogue/filters, an operator and its operands. Exclusions nest under not."
},
"AllGroup": {
"type": "object",
"required": [
"all"
],
"properties": {
"all": {
"type": "array",
"items": {
"$ref": "#/$defs/WhereNode"
},
"minItems": 1
}
},
"description": "AND: every node inside must match.",
"additionalProperties": false
},
"AnyGroup": {
"type": "object",
"required": [
"any"
],
"properties": {
"any": {
"type": "array",
"items": {
"$ref": "#/$defs/WhereNode"
},
"minItems": 1
}
},
"description": "OR: at least one node inside must match.",
"additionalProperties": false
},
"Audience": {
"type": "object",
"title": "MyDataHub audience definition (mydatahub.audience/1)",
"required": [
"schema"
],
"properties": {
"where": {
"$ref": "#/$defs/WhereNode",
"description": "The filters. Left out, the audience is the whole dataset after the defaults."
},
"dedupe": {
"enum": [
"none",
"one_per_company",
"one_per_site"
],
"type": "string",
"description": "none keeps every matching contact, one_per_company keeps one contact per company, one_per_site keeps one per site. Default none."
},
"schema": {
"type": "string",
"const": "mydatahub.audience/1",
"description": "The definition's namespace and version. Older versions are upgraded by a pure function."
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
},
"email_policy": {
"$ref": "#/$defs/EmailPolicy"
},
"dataset_version": {
"type": "string",
"pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
"examples": [
"2026-W39"
],
"description": "The weekly build to count against, such as 2026-W39. Left out, the current version is filled in and returned."
}
},
"description": "Who you want, as filters grouped by entity (company., site., contact., email., phone., signal.). The server fills its defaults (active companies, named emails, corporate subscribers, the current dataset_version) and returns the effective definition with every count.",
"additionalProperties": false
},
"InFilter": {
"type": "object",
"examples": [
{
"op": "in",
"field": "company.sic_2007",
"values": [
"C"
]
}
],
"required": [
"field",
"op",
"values"
],
"properties": {
"op": {
"type": "string",
"const": "in"
},
"field": {
"enum": [
"company.sic_2007",
"company.business_class",
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"company.type",
"company.status",
"company.subscriber_class",
"company.companies_house_number",
"site.region",
"site.county",
"site.town",
"site.postcode",
"contact.title_family",
"contact.job_function",
"contact.job_level_rank",
"contact.premium",
"email.exists",
"email.type",
"phone.exists",
"phone.tps_ctps_status"
],
"type": "string"
},
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
},
{
"type": "boolean"
}
],
"description": "A code, a rank or a boolean, as the field's catalogue lists it."
},
"maxItems": 10000,
"minItems": 1
}
},
"description": "The field holds one of the listed codes.",
"additionalProperties": false
},
"NotGroup": {
"type": "object",
"required": [
"not"
],
"properties": {
"not": {
"$ref": "#/$defs/WhereNode"
}
},
"description": "Negation: the single node inside must not match.",
"additionalProperties": false
},
"GteFilter": {
"type": "object",
"examples": [
{
"op": "gte",
"field": "company.employee_band",
"value": "50-99"
}
],
"required": [
"field",
"op",
"value"
],
"properties": {
"op": {
"type": "string",
"const": "gte"
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"email.deliverability_score"
],
"type": "string"
},
"value": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
}
},
"description": "The field is at or after the value in its order: for bands, the band and every larger one.",
"additionalProperties": false
},
"LteFilter": {
"type": "object",
"examples": [
{
"op": "lte",
"field": "contact.job_level_rank",
"value": 6
}
],
"required": [
"field",
"op",
"value"
],
"properties": {
"op": {
"type": "string",
"const": "lte"
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"contact.company_contact_rank",
"email.deliverability_score"
],
"type": "string"
},
"value": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
}
},
"description": "The field is at or before the value in its order. Rank 1 is the most senior, so Director and above is contact.job_level_rank lte 6.",
"additionalProperties": false
},
"WhereNode": {
"anyOf": [
{
"$ref": "#/$defs/AllGroup"
},
{
"$ref": "#/$defs/AnyGroup"
},
{
"$ref": "#/$defs/NotGroup"
},
{
"$ref": "#/$defs/BundleNode"
},
{
"$ref": "#/$defs/Filter"
}
],
"description": "A group (all, any, not), a title bundle or a filter. Groups nest up to 32 deep, and a where tree holds up to 1,000 filters, groups and bundles."
},
"BundleNode": {
"type": "object",
"required": [
"bundle"
],
"properties": {
"bundle": {
"enum": [
"sdm",
"manager_and_above",
"owner_managed"
],
"type": "string"
}
},
"description": "A title bundle, resolved to its filters in the effective definition: sdm (senior decision makers), manager_and_above (managers and above), owner_managed (owner managed).",
"additionalProperties": false
},
"AudienceRef": {
"anyOf": [
{
"type": "string",
"pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
],
"description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA."
},
{
"$ref": "#/$defs/Audience"
}
],
"description": "An audience definition (mydatahub.audience/1) inline, or the aud_ id of a saved audience."
},
"EmailPolicy": {
"type": "object",
"properties": {
"allow_catch_all": {
"type": "boolean",
"description": "Whether catch-all addresses count. Default false."
},
"min_deliverability_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Lowest deliverability score counted, 0 to 100. Default 70."
}
},
"description": "Email quality floor. Defaults: min_deliverability_score 70, allow_catch_all false.",
"additionalProperties": false
},
"PlaceCentre": {
"type": "object",
"required": [
"place"
],
"properties": {
"code": {
"type": "string",
"maxLength": 20,
"minLength": 1,
"description": "The ONS geography code of the chosen candidate when resolve_location found more than one, such as E08000035 for the Leeds district."
},
"place": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "A place name, resolved with resolve_location, such as Leeds."
}
},
"description": "A named place. Ambiguous names come back from resolve_location as candidates, never a silent choice.",
"additionalProperties": false
},
"PointCentre": {
"type": "object",
"required": [
"lat",
"lon"
],
"properties": {
"lat": {
"type": "number",
"maximum": 61,
"minimum": 49
},
"lon": {
"type": "number",
"maximum": 2,
"minimum": -9
}
},
"description": "A latitude and longitude in WGS84 degrees.",
"additionalProperties": false
},
"SinceFilter": {
"type": "object",
"examples": [
{
"op": "since",
"days": 90,
"field": "signal.type",
"values": [
"company.incorporated"
]
}
],
"required": [
"field",
"op",
"days"
],
"properties": {
"op": {
"type": "string",
"const": "since"
},
"days": {
"type": "integer",
"maximum": 3650,
"minimum": 1
},
"field": {
"enum": [
"contact.last_validated_at",
"email.last_verified_at",
"signal.type",
"signal.observed_at"
],
"type": "string"
},
"values": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 10000,
"minItems": 1,
"description": "For signal.type only: the signal types to look for, such as company.incorporated."
}
},
"description": "Within the last N days: a date field, or a Companies House signal of the listed types on signal.type.",
"additionalProperties": false
},
"InListFilter": {
"type": "object",
"examples": [
{
"op": "in_list",
"field": "email.address_sha256",
"list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
}
],
"required": [
"field",
"op",
"list_id"
],
"properties": {
"op": {
"type": "string",
"const": "in_list"
},
"field": {
"enum": [
"company.companies_house_number",
"contact.title",
"email.address_sha256",
"email.domain_sha256",
"phone.e164_sha256"
],
"type": "string"
},
"list_id": {
"type": "string",
"pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
],
"description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA."
}
},
"description": "The record's hashed email, domain, phone, company number or title term is on a suppression list. Usually nested under not; each list reports the records it removed.",
"additionalProperties": false
},
"RadiusCentre": {
"anyOf": [
{
"$ref": "#/$defs/PlaceCentre"
},
{
"$ref": "#/$defs/PostcodeCentre"
},
{
"$ref": "#/$defs/PointCentre"
}
],
"description": "The centre of a radius: a place, a postcode or a latitude and longitude."
},
"BetweenFilter": {
"type": "object",
"examples": [
{
"op": "between",
"to": "200-349",
"from": "10-19",
"field": "company.employee_band"
}
],
"required": [
"field",
"op",
"from",
"to"
],
"properties": {
"op": {
"type": "string",
"const": "between"
},
"to": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
},
"from": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"email.deliverability_score"
],
"type": "string"
}
},
"description": "The field lies from one value to another inclusive, over the field's order.",
"additionalProperties": false
},
"MatchesFilter": {
"type": "object",
"allOf": [
{
"if": {
"type": "object",
"required": [
"mode"
],
"properties": {
"mode": {
"const": "exact"
}
}
},
"then": {
"type": "object",
"properties": {
"expand": {
"type": "array",
"maxItems": 0
},
"exclude_terms": {
"type": "array",
"maxItems": 0
}
}
}
}
],
"examples": [
{
"op": "matches",
"mode": "contains",
"field": "contact.title",
"terms": [
"marketing manager"
],
"expand": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations"
]
}
],
"required": [
"field",
"op",
"terms"
],
"properties": {
"op": {
"type": "string",
"const": "matches"
},
"mode": {
"enum": [
"contains",
"starts_with",
"exact"
],
"type": "string",
"description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
},
"field": {
"enum": [
"contact.title"
],
"type": "string"
},
"terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"minItems": 1
},
"expand": {
"type": "array",
"items": {
"enum": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations",
"permutations"
],
"type": "string"
},
"maxItems": 5,
"description": "Expansion sets to apply, each once: plural_singular, department_synonyms, ampersand_and, abbreviations, permutations. Left out, the first four apply; an empty list applies none. Not used with mode exact.",
"uniqueItems": true
},
"exclude_terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Expanded terms removed by hand. Kept in the definition so the count stays reproducible when the title dictionary changes."
}
},
"description": "Job title keyword match. mode contains (the default) or starts_with expands each term with the expansion sets; mode exact matches verbatim titles. Every expanded term is returned with the count.",
"additionalProperties": false
},
"PostcodeCentre": {
"type": "object",
"required": [
"postcode"
],
"properties": {
"postcode": {
"type": "string",
"pattern": "^[A-Za-z]{1,2}([0-9][0-9A-Za-z]?( [0-9]([A-Za-z]{2})?| ?[0-9][A-Za-z]{2})?)?$",
"description": "The centroid of a postcode unit, sector, district or area, such as LS1 4AP."
}
},
"description": "A postcode centroid from ONSPD.",
"additionalProperties": false
},
"WithinRadiusFilter": {
"type": "object",
"examples": [
{
"op": "within_radius",
"field": "site.location",
"centre": {
"place": "Leeds"
},
"radius_miles": 20
}
],
"required": [
"field",
"op",
"centre",
"radius_miles"
],
"properties": {
"op": {
"type": "string",
"const": "within_radius"
},
"field": {
"enum": [
"site.location"
],
"type": "string"
},
"centre": {
"$ref": "#/$defs/RadiusCentre"
},
"radius_miles": {
"type": "number",
"maximum": 100,
"minimum": 1,
"description": "Radius in miles, 1 to 100. Under 5 miles needs an account."
}
},
"description": "Sites within radius_miles of the centre. The count reports the centroid used and the postcodes matched.",
"additionalProperties": false
}
},
"required": [
"audience"
],
"properties": {
"level": {
"enum": [
"contact",
"company"
],
"type": "string",
"default": "contact",
"description": "contact (the default) or company. Contacts and companies come back together either way."
},
"audience": {
"$ref": "#/$defs/AudienceRef"
},
"breakdown_by": {
"type": "array",
"items": {
"enum": [
"company.sic_2007",
"company.business_class",
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"company.type",
"company.status",
"company.subscriber_class",
"site.region",
"site.county",
"site.town",
"site.postcode",
"contact.title_family",
"contact.job_function",
"contact.job_level_rank",
"email.exists",
"email.type",
"phone.exists",
"phone.tps_ctps_status"
],
"type": "string",
"description": "A field a count can be broken down by."
},
"maxItems": 3,
"description": "Up to three fields to break the count down by, each once, such as industry by seniority by region. Returns the top 50 cells per field plus other.",
"uniqueItems": true
}
},
"description": "An audience, a level and up to three breakdown fields. Free, and needs no account.",
"additionalProperties": false
}Deprecated: spent credits on a saved list when the model set a confirmation flag, and no longer does. Use quote_order, then create_order instead. The flag is ignored, since a flag set by a model is never consent: the call makes a machine quote for the list, and the user confirms the spend in a form or on mydatahub.emailmovers.com, or an agent key covers it within its limits; otherwise nothing is charged and it returns the approval_url. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Spends 1 credit per complete UK record against a live machine quote from quote_order, and queues the order. It needs the quote_id and an idempotency_key to reuse on any retry, so a retry never charges twice; a flag set by a model is never consent. Where the host supports elicitation the user confirms the spend in a form or on mydatahub.emailmovers.com; otherwise an agent key must cover it within its per-order cap and monthly budget. If neither applies nothing is charged: the result is a confirmation-required error with an approval_url to give the user, so keep the quote_id; a short balance returns a top_up_url. Call get_order until the status is ready, then fetch_order_records. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| delivery | array | api (fetch records), csv (signed download) and google_sheets. Default api. |
| quote_id* | string | A live machine quote from quote_order. Without one nothing is charged. |
| idempotency_key* | string | Any unique string, such as a V4 UUID. Reuse it when retrying the same order so it is never charged twice; a different order needs a new key. |
| confirmation_token | string | The token the approval page on mydatahub.emailmovers.com returns once the signed-in person approves. It is bound to that person (their sub), this spend (the machine quote_id, or the enrichment or push) and an expiry no later than the quote's, and it is redeemable once. |
{
"type": "object",
"required": [
"quote_id",
"idempotency_key"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"delivery": {
"type": "array",
"items": {
"enum": [
"api",
"csv",
"google_sheets"
],
"type": "string"
},
"minItems": 1,
"description": "api (fetch records), csv (signed download) and google_sheets. Default api."
},
"quote_id": {
"type": "string",
"pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
],
"description": "A live machine quote from quote_order. Without one nothing is charged."
},
"idempotency_key": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Any unique string, such as a V4 UUID. Reuse it when retrying the same order so it is never charged twice; a different order needs a new key."
},
"confirmation_token": {
"type": "string",
"maxLength": 2000,
"minLength": 16,
"description": "The token the approval page on mydatahub.emailmovers.com returns once the signed-in person approves. It is bound to that person (their sub), this spend (the machine quote_id, or the enrichment or push) and an expiry no later than the quote's, and it is redeemable once."
}
},
"additionalProperties": false
}Deprecated: adds filters to a count held in the server session. Use compile_audience, then count_audience instead. count_audience takes the whole audience definition in one call, so there is no session state to build up, and compile_audience turns a brief into that definition. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Returns the full record for one known person, matched by email or by name with a company name, number or domain. It spends 1 credit only on a confident match, and 0 on no match or when you already hold the record under licence, so a repeat never charges twice. Like create_order it needs the user's confirmation (a form, or the confirmation_token from an approval_url) or an agent key whose allowed_tools include enrich_contact within its per-order cap and monthly budget; otherwise nothing is charged and it returns confirmation-required or agent-budget-exceeded. It needs enrich:write; use it for a single named person, and the result gives credits_charged and the balance left. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| string | ||
| domain | string | |
| last_name | string | |
| first_name | string | |
| company_name | string | |
| company_number | string | Eight characters in upper case, such as 05046417 or SC123456. |
| confirmation_token | string | The token the approval page on mydatahub.emailmovers.com returns once the signed-in person approves. It is bound to that person (their sub), this spend (the machine quote_id, or the enrichment or push) and an expiry no later than the quote's, and it is redeemable once. |
{
"type": "object",
"anyOf": [
{
"type": "object",
"required": [
"email"
],
"properties": {
"email": true
}
},
{
"type": "object",
"anyOf": [
{
"type": "object",
"required": [
"company_name"
],
"properties": {
"company_name": true
}
},
{
"type": "object",
"required": [
"company_number"
],
"properties": {
"company_number": true
}
},
{
"type": "object",
"required": [
"domain"
],
"properties": {
"domain": true
}
}
],
"required": [
"first_name",
"last_name"
],
"properties": {
"last_name": true,
"first_name": true
}
}
],
"properties": {
"email": {
"type": "string",
"format": "email"
},
"domain": {
"type": "string",
"maxLength": 253,
"minLength": 3
},
"last_name": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"first_name": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"company_name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"company_number": {
"type": "string",
"pattern": "^[A-Z0-9]{8}$",
"description": "Eight characters in upper case, such as 05046417 or SC123456."
},
"confirmation_token": {
"type": "string",
"maxLength": 2000,
"minLength": 16,
"description": "The token the approval page on mydatahub.emailmovers.com returns once the signed-in person approves. It is bound to that person (their sub), this spend (the machine quote_id, or the enrichment or push) and an expiry no later than the quote's, and it is redeemable once."
}
},
"description": "One known person to match. Send email, or first_name and last_name with company_name, company_number or domain.",
"additionalProperties": false
}Expands title keywords into every matching title (plurals, department synonyms, ampersands, abbreviations such as CEO), each with a count, or shows what a bundle such as sdm resolves to. Use it before counting so the user can see and edit which titles a keyword covers; nothing is expanded silently. Free and needs no account. Put the returned filter into the audience, then call count_audience. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| mode | string | contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion. |
| terms | array | Title keywords to expand, such as marketing manager. |
| bundle | string | A title bundle to show: sdm, manager_and_above or owner_managed. |
| expand | array | Expansion sets to apply, each once. Left out, the four default sets apply. |
| dataset | string | The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served. |
{
"type": "object",
"oneOf": [
{
"type": "object",
"required": [
"terms"
],
"properties": {
"terms": true
}
},
{
"type": "object",
"required": [
"bundle"
],
"properties": {
"bundle": true
}
}
],
"properties": {
"mode": {
"enum": [
"contains",
"starts_with",
"exact"
],
"type": "string",
"description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
},
"terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 50,
"minItems": 1,
"description": "Title keywords to expand, such as marketing manager."
},
"bundle": {
"enum": [
"sdm",
"manager_and_above",
"owner_managed"
],
"type": "string",
"description": "A title bundle to show: sdm, manager_and_above or owner_managed."
},
"expand": {
"type": "array",
"items": {
"enum": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations",
"permutations"
],
"type": "string"
},
"description": "Expansion sets to apply, each once. Left out, the four default sets apply.",
"uniqueItems": true
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
}
},
"description": "Keywords or a bundle to expand into an editable title list: exactly one of terms or bundle.",
"additionalProperties": false
}Returns a page of an order's delivered records (50 by default, up to 100) with the licence block on every page, as JSON or, on request, as CSV. Pages stay under about 8,000 tokens, with approx_tokens on each; pass next_cursor to continue. Fetching again under licence costs 0 credits; it needs records:read. Call check_suppression before any send, and get_compliance_receipt for proof of screening. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Records per page, 1 to 100 over MCP so a result stays under about 8,000 tokens. Default 50. |
| cursor | string | An opaque cursor from next_cursor. Pass it back unchanged. |
| fields | array | Columns to return; default the order's field set. |
| format | string | json (default) or csv. |
| order_id* | string | The order whose records to fetch. It must be ready. |
{
"type": "object",
"required": [
"order_id"
],
"properties": {
"limit": {
"type": "integer",
"default": 50,
"maximum": 100,
"minimum": 1,
"description": "Records per page, 1 to 100 over MCP so a result stays under about 8,000 tokens. Default 50."
},
"cursor": {
"type": "string",
"maxLength": 512,
"minLength": 1,
"description": "An opaque cursor from next_cursor. Pass it back unchanged."
},
"fields": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9_]+$"
},
"description": "Columns to return; default the order's field set."
},
"format": {
"enum": [
"json",
"csv"
],
"type": "string",
"default": "json",
"description": "json (default) or csv."
},
"order_id": {
"type": "string",
"pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
],
"description": "The order whose records to fetch. It must be ready."
}
},
"additionalProperties": false
}Returns the organisation's credit balance by source, plan, per-action prices and rate limit, and for an agent key its monthly budget and per-order cap. Use it before quoting a large order, or when a spend is refused, to see what remains. Free; it needs a token with account:read. Top-ups happen on mydatahub.emailmovers.com, never inside a tool. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Returns an order's signed compliance receipt: an ES256 JWS with its decoded claims and a PDF link, covering records delivered, suppression removals, subscriber classes, TPS screening, Article 14 status, the licence and the file hash. Use it to prove to the user, a colleague or another agent that a list is licensed and screened; anyone can verify it with POST /v1/compliance/receipts/verify. Free; it needs orders:read. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| order_id* | string | The order the receipt covers. |
{
"type": "object",
"required": [
"order_id"
],
"properties": {
"order_id": {
"type": "string",
"pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
],
"description": "The order the receipt covers."
}
},
"additionalProperties": false
}Deprecated: returns the count for the filters held in the server session. Use count_audience instead. It returns Total, New to you and Emailable with breakdowns, quality, the compliance summary, a price estimate and a count id. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Deprecated: returns the credit balance. Use get_account instead. It returns the balance by source, the plan, per-action prices, the rate limit and any agent key budget; balances carry over one for one. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Returns one order's status (queued, building, verifying, ready, failed or cancelled), counts, charges, licence and links to its records, download and receipt, or the recent orders when order_id is left out. Use it after create_order to wait for ready, or rely on the order.ready webhook. Free; it needs orders:read. Call fetch_order_records once the status is ready. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Items per page, 1 to 100. Default 25. |
| cursor | string | An opaque cursor from next_cursor. Pass it back unchanged. |
| status | string | queued, building, verifying, ready; failed if processing failed; cancelled (only while queued). |
| order_id | string | The order to return. Leave it out for the recent orders, newest first. |
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Items per page, 1 to 100. Default 25."
},
"cursor": {
"type": "string",
"maxLength": 512,
"minLength": 1,
"description": "An opaque cursor from next_cursor. Pass it back unchanged."
},
"status": {
"enum": [
"queued",
"building",
"verifying",
"ready",
"failed",
"cancelled"
],
"type": "string",
"description": "queued, building, verifying, ready; failed if processing failed; cancelled (only while queued)."
},
"order_id": {
"type": "string",
"pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
],
"description": "The order to return. Leave it out for the recent orders, newest first."
}
},
"additionalProperties": false
}Deprecated: lists the columns of one field bundle. Use list_field_sets instead. list_field_sets returns every field set with its exact columns and credits per record. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Deprecated: lists the field bundles an order can deliver. Use list_field_sets instead. The old bundles become named field sets with their exact columns; the five test bundles are removed. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Returns the plans of MyDataHub by Emailmovers, the UK B2B count engine: credit packs, credit rules, licence terms, the bounce warranty and the free trial, in GBP excluding VAT. Use it when the user asks what a list costs or which plan fits; it is free and needs no account. One credit buys one complete UK record at the same price in the app, the API and here. Call get_account for the caller's own balance, or count_audience to size a list. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Deprecated: lists the saved lists of the organisation. Use list_audiences instead. Saved lists carry over as audiences (aud_) in the same organisation, with their current counts. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Lists the organisation's saved audiences with their current counts and last refresh, newest first, optionally filtered by name. Use it to find an aud_ id to count, quote or share. Free; it needs audiences:read. Pass an aud_ id to count_audience for a fresh count. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| q | string | Filter by name. |
| limit | integer | Items per page, 1 to 100. Default 25. |
| cursor | string | An opaque cursor from next_cursor. Pass it back unchanged. |
{
"type": "object",
"properties": {
"q": {
"type": "string",
"maxLength": 100,
"description": "Filter by name."
},
"limit": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Items per page, 1 to 100. Default 25."
},
"cursor": {
"type": "string",
"maxLength": 512,
"minLength": 1,
"description": "An opaque cursor from next_cursor. Pass it back unchanged."
}
},
"additionalProperties": false
}Lists the field sets an order can deliver, such as standard or standard_telephone, with their exact columns. Every field set costs 1 credit a record, with no telephone, download or API surcharge. Use it to pick the field_set for quote_order; it is free and needs no account. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Items per page, 1 to 100. Default 25. |
| cursor | string | An opaque cursor from next_cursor. Pass it back unchanged. |
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Items per page, 1 to 100. Default 25."
},
"cursor": {
"type": "string",
"maxLength": 512,
"minLength": 1,
"description": "An opaque cursor from next_cursor. Pass it back unchanged."
}
},
"additionalProperties": false
}Lists every filterable field of the audience definition (mydatahub.audience/1) with its group, type, operators, value count and default, plus the datasets. Use it first to learn field names such as company.employee_band or site.town before building an audience by hand. Free and needs no account; the same catalogue is the mydatahub://catalogue resource. Call search_filter_values to find the codes for one field. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| dataset | string | The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served. |
{
"type": "object",
"properties": {
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
}
},
"additionalProperties": false
}Looks up one company by Companies House number, domain or name and returns its Companies House fields and compliance facts, and for a signed-in caller the contacts held there by job level. It returns no contact details: use enrich_contact for one known person, or count_audience for everyone at the company. Free and needs no account, though the contacts held are a single company count that needs an account (null when signed out). Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| town | string | Narrows a name search. |
| domain | string | |
| company_number | string | Eight characters in upper case, such as 05046417 or SC123456. |
{
"type": "object",
"oneOf": [
{
"type": "object",
"required": [
"company_number"
],
"properties": {
"company_number": true
}
},
{
"type": "object",
"required": [
"domain"
],
"properties": {
"domain": true
}
},
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": true
}
}
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 2
},
"town": {
"type": "string",
"maxLength": 100,
"description": "Narrows a name search."
},
"domain": {
"type": "string",
"maxLength": 253,
"minLength": 3
},
"company_number": {
"type": "string",
"pattern": "^[A-Z0-9]{8}$",
"description": "Eight characters in upper case, such as 05046417 or SC123456."
}
},
"description": "A company by exactly one of number, domain or name.",
"additionalProperties": false
}Returns up to 25 masked sample rows (10 by default) for an audience or a count id, each with verification badges, why it matches and a provenance card. Use it after count_audience to show the user what the records look like before quoting. Free: emails and phones are masked on the server, a repeat returns the same rows, and no rows come back when the count is under 25. Call quote_order next to price the records. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Rows to return, 1 to 25. Default 10. |
| shuffle | boolean | Draw a new seed. Counts against your rate budget and is logged. Default false, so a repeat returns the same rows. |
| audience | any | |
| count_id | string | A count id instead of an audience. |
{
"type": "object",
"$defs": {
"Filter": {
"oneOf": [
{
"$ref": "#/$defs/InFilter"
},
{
"$ref": "#/$defs/BetweenFilter"
},
{
"$ref": "#/$defs/GteFilter"
},
{
"$ref": "#/$defs/LteFilter"
},
{
"$ref": "#/$defs/MatchesFilter"
},
{
"$ref": "#/$defs/WithinRadiusFilter"
},
{
"$ref": "#/$defs/InListFilter"
},
{
"$ref": "#/$defs/SinceFilter"
}
],
"description": "One criterion: a field from GET /v1/catalogue/filters, an operator and its operands. Exclusions nest under not."
},
"AllGroup": {
"type": "object",
"required": [
"all"
],
"properties": {
"all": {
"type": "array",
"items": {
"$ref": "#/$defs/WhereNode"
},
"minItems": 1
}
},
"description": "AND: every node inside must match.",
"additionalProperties": false
},
"AnyGroup": {
"type": "object",
"required": [
"any"
],
"properties": {
"any": {
"type": "array",
"items": {
"$ref": "#/$defs/WhereNode"
},
"minItems": 1
}
},
"description": "OR: at least one node inside must match.",
"additionalProperties": false
},
"Audience": {
"type": "object",
"title": "MyDataHub audience definition (mydatahub.audience/1)",
"required": [
"schema"
],
"properties": {
"where": {
"$ref": "#/$defs/WhereNode",
"description": "The filters. Left out, the audience is the whole dataset after the defaults."
},
"dedupe": {
"enum": [
"none",
"one_per_company",
"one_per_site"
],
"type": "string",
"description": "none keeps every matching contact, one_per_company keeps one contact per company, one_per_site keeps one per site. Default none."
},
"schema": {
"type": "string",
"const": "mydatahub.audience/1",
"description": "The definition's namespace and version. Older versions are upgraded by a pure function."
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
},
"email_policy": {
"$ref": "#/$defs/EmailPolicy"
},
"dataset_version": {
"type": "string",
"pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
"examples": [
"2026-W39"
],
"description": "The weekly build to count against, such as 2026-W39. Left out, the current version is filled in and returned."
}
},
"description": "Who you want, as filters grouped by entity (company., site., contact., email., phone., signal.). The server fills its defaults (active companies, named emails, corporate subscribers, the current dataset_version) and returns the effective definition with every count.",
"additionalProperties": false
},
"InFilter": {
"type": "object",
"examples": [
{
"op": "in",
"field": "company.sic_2007",
"values": [
"C"
]
}
],
"required": [
"field",
"op",
"values"
],
"properties": {
"op": {
"type": "string",
"const": "in"
},
"field": {
"enum": [
"company.sic_2007",
"company.business_class",
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"company.type",
"company.status",
"company.subscriber_class",
"company.companies_house_number",
"site.region",
"site.county",
"site.town",
"site.postcode",
"contact.title_family",
"contact.job_function",
"contact.job_level_rank",
"contact.premium",
"email.exists",
"email.type",
"phone.exists",
"phone.tps_ctps_status"
],
"type": "string"
},
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
},
{
"type": "boolean"
}
],
"description": "A code, a rank or a boolean, as the field's catalogue lists it."
},
"maxItems": 10000,
"minItems": 1
}
},
"description": "The field holds one of the listed codes.",
"additionalProperties": false
},
"NotGroup": {
"type": "object",
"required": [
"not"
],
"properties": {
"not": {
"$ref": "#/$defs/WhereNode"
}
},
"description": "Negation: the single node inside must not match.",
"additionalProperties": false
},
"GteFilter": {
"type": "object",
"examples": [
{
"op": "gte",
"field": "company.employee_band",
"value": "50-99"
}
],
"required": [
"field",
"op",
"value"
],
"properties": {
"op": {
"type": "string",
"const": "gte"
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"email.deliverability_score"
],
"type": "string"
},
"value": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
}
},
"description": "The field is at or after the value in its order: for bands, the band and every larger one.",
"additionalProperties": false
},
"LteFilter": {
"type": "object",
"examples": [
{
"op": "lte",
"field": "contact.job_level_rank",
"value": 6
}
],
"required": [
"field",
"op",
"value"
],
"properties": {
"op": {
"type": "string",
"const": "lte"
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"contact.company_contact_rank",
"email.deliverability_score"
],
"type": "string"
},
"value": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
}
},
"description": "The field is at or before the value in its order. Rank 1 is the most senior, so Director and above is contact.job_level_rank lte 6.",
"additionalProperties": false
},
"WhereNode": {
"anyOf": [
{
"$ref": "#/$defs/AllGroup"
},
{
"$ref": "#/$defs/AnyGroup"
},
{
"$ref": "#/$defs/NotGroup"
},
{
"$ref": "#/$defs/BundleNode"
},
{
"$ref": "#/$defs/Filter"
}
],
"description": "A group (all, any, not), a title bundle or a filter. Groups nest up to 32 deep, and a where tree holds up to 1,000 filters, groups and bundles."
},
"BundleNode": {
"type": "object",
"required": [
"bundle"
],
"properties": {
"bundle": {
"enum": [
"sdm",
"manager_and_above",
"owner_managed"
],
"type": "string"
}
},
"description": "A title bundle, resolved to its filters in the effective definition: sdm (senior decision makers), manager_and_above (managers and above), owner_managed (owner managed).",
"additionalProperties": false
},
"AudienceRef": {
"anyOf": [
{
"type": "string",
"pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
],
"description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA."
},
{
"$ref": "#/$defs/Audience"
}
],
"description": "An audience definition (mydatahub.audience/1) inline, or the aud_ id of a saved audience."
},
"EmailPolicy": {
"type": "object",
"properties": {
"allow_catch_all": {
"type": "boolean",
"description": "Whether catch-all addresses count. Default false."
},
"min_deliverability_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Lowest deliverability score counted, 0 to 100. Default 70."
}
},
"description": "Email quality floor. Defaults: min_deliverability_score 70, allow_catch_all false.",
"additionalProperties": false
},
"PlaceCentre": {
"type": "object",
"required": [
"place"
],
"properties": {
"code": {
"type": "string",
"maxLength": 20,
"minLength": 1,
"description": "The ONS geography code of the chosen candidate when resolve_location found more than one, such as E08000035 for the Leeds district."
},
"place": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "A place name, resolved with resolve_location, such as Leeds."
}
},
"description": "A named place. Ambiguous names come back from resolve_location as candidates, never a silent choice.",
"additionalProperties": false
},
"PointCentre": {
"type": "object",
"required": [
"lat",
"lon"
],
"properties": {
"lat": {
"type": "number",
"maximum": 61,
"minimum": 49
},
"lon": {
"type": "number",
"maximum": 2,
"minimum": -9
}
},
"description": "A latitude and longitude in WGS84 degrees.",
"additionalProperties": false
},
"SinceFilter": {
"type": "object",
"examples": [
{
"op": "since",
"days": 90,
"field": "signal.type",
"values": [
"company.incorporated"
]
}
],
"required": [
"field",
"op",
"days"
],
"properties": {
"op": {
"type": "string",
"const": "since"
},
"days": {
"type": "integer",
"maximum": 3650,
"minimum": 1
},
"field": {
"enum": [
"contact.last_validated_at",
"email.last_verified_at",
"signal.type",
"signal.observed_at"
],
"type": "string"
},
"values": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 10000,
"minItems": 1,
"description": "For signal.type only: the signal types to look for, such as company.incorporated."
}
},
"description": "Within the last N days: a date field, or a Companies House signal of the listed types on signal.type.",
"additionalProperties": false
},
"InListFilter": {
"type": "object",
"examples": [
{
"op": "in_list",
"field": "email.address_sha256",
"list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
}
],
"required": [
"field",
"op",
"list_id"
],
"properties": {
"op": {
"type": "string",
"const": "in_list"
},
"field": {
"enum": [
"company.companies_house_number",
"contact.title",
"email.address_sha256",
"email.domain_sha256",
"phone.e164_sha256"
],
"type": "string"
},
"list_id": {
"type": "string",
"pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
],
"description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA."
}
},
"description": "The record's hashed email, domain, phone, company number or title term is on a suppression list. Usually nested under not; each list reports the records it removed.",
"additionalProperties": false
},
"RadiusCentre": {
"anyOf": [
{
"$ref": "#/$defs/PlaceCentre"
},
{
"$ref": "#/$defs/PostcodeCentre"
},
{
"$ref": "#/$defs/PointCentre"
}
],
"description": "The centre of a radius: a place, a postcode or a latitude and longitude."
},
"BetweenFilter": {
"type": "object",
"examples": [
{
"op": "between",
"to": "200-349",
"from": "10-19",
"field": "company.employee_band"
}
],
"required": [
"field",
"op",
"from",
"to"
],
"properties": {
"op": {
"type": "string",
"const": "between"
},
"to": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
},
"from": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"email.deliverability_score"
],
"type": "string"
}
},
"description": "The field lies from one value to another inclusive, over the field's order.",
"additionalProperties": false
},
"MatchesFilter": {
"type": "object",
"allOf": [
{
"if": {
"type": "object",
"required": [
"mode"
],
"properties": {
"mode": {
"const": "exact"
}
}
},
"then": {
"type": "object",
"properties": {
"expand": {
"type": "array",
"maxItems": 0
},
"exclude_terms": {
"type": "array",
"maxItems": 0
}
}
}
}
],
"examples": [
{
"op": "matches",
"mode": "contains",
"field": "contact.title",
"terms": [
"marketing manager"
],
"expand": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations"
]
}
],
"required": [
"field",
"op",
"terms"
],
"properties": {
"op": {
"type": "string",
"const": "matches"
},
"mode": {
"enum": [
"contains",
"starts_with",
"exact"
],
"type": "string",
"description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
},
"field": {
"enum": [
"contact.title"
],
"type": "string"
},
"terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"minItems": 1
},
"expand": {
"type": "array",
"items": {
"enum": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations",
"permutations"
],
"type": "string"
},
"maxItems": 5,
"description": "Expansion sets to apply, each once: plural_singular, department_synonyms, ampersand_and, abbreviations, permutations. Left out, the first four apply; an empty list applies none. Not used with mode exact.",
"uniqueItems": true
},
"exclude_terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Expanded terms removed by hand. Kept in the definition so the count stays reproducible when the title dictionary changes."
}
},
"description": "Job title keyword match. mode contains (the default) or starts_with expands each term with the expansion sets; mode exact matches verbatim titles. Every expanded term is returned with the count.",
"additionalProperties": false
},
"PostcodeCentre": {
"type": "object",
"required": [
"postcode"
],
"properties": {
"postcode": {
"type": "string",
"pattern": "^[A-Za-z]{1,2}([0-9][0-9A-Za-z]?( [0-9]([A-Za-z]{2})?| ?[0-9][A-Za-z]{2})?)?$",
"description": "The centroid of a postcode unit, sector, district or area, such as LS1 4AP."
}
},
"description": "A postcode centroid from ONSPD.",
"additionalProperties": false
},
"WithinRadiusFilter": {
"type": "object",
"examples": [
{
"op": "within_radius",
"field": "site.location",
"centre": {
"place": "Leeds"
},
"radius_miles": 20
}
],
"required": [
"field",
"op",
"centre",
"radius_miles"
],
"properties": {
"op": {
"type": "string",
"const": "within_radius"
},
"field": {
"enum": [
"site.location"
],
"type": "string"
},
"centre": {
"$ref": "#/$defs/RadiusCentre"
},
"radius_miles": {
"type": "number",
"maximum": 100,
"minimum": 1,
"description": "Radius in miles, 1 to 100. Under 5 miles needs an account."
}
},
"description": "Sites within radius_miles of the centre. The count reports the centroid used and the postcodes matched.",
"additionalProperties": false
}
},
"oneOf": [
{
"type": "object",
"required": [
"audience"
],
"properties": {
"audience": true
}
},
{
"type": "object",
"required": [
"count_id"
],
"properties": {
"count_id": true
}
}
],
"properties": {
"limit": {
"type": "integer",
"default": 10,
"maximum": 25,
"minimum": 1,
"description": "Rows to return, 1 to 25. Default 10."
},
"shuffle": {
"type": "boolean",
"default": false,
"description": "Draw a new seed. Counts against your rate budget and is logged. Default false, so a repeat returns the same rows."
},
"audience": {
"$ref": "#/$defs/AudienceRef"
},
"count_id": {
"type": "string",
"pattern": "^cnt_[A-Za-z2-7]{20}$",
"examples": [
"cnt_7K2PQ4MAXN3R6TBY5WDZ"
],
"description": "A count id instead of an audience."
}
},
"description": "The audience or count to sample: exactly one of audience or count_id.",
"additionalProperties": false
}Pushes an order's records to a connected CRM such as HubSpot or Salesforce, keyed on mydatahub_record_id, as record operations only: nothing is ever sent to the contacts. dry_run defaults to true and reports what would be created, updated or skipped; a live push needs the user's confirmation or an agent key allowed push_to_crm on that connection, or it returns confirmation-required. Free; it needs pushes:write and a connection made in the app. Show the dry run to the user before a live push. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| dry_run | boolean | Default true: report what would change without writing. A live push needs approval: a person's confirmation, or an agent key allowed push_to_crm on this connection. |
| order_id* | string | The order whose records to push. |
| connection_id* | string | Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G. |
| update_existing | boolean | Update records already in the CRM, matched on mydatahub_record_id. Default true. |
| confirmation_token | string | The token the approval page on mydatahub.emailmovers.com returns once the signed-in person approves. It is bound to that person (their sub), this spend (the machine quote_id, or the enrichment or push) and an expiry no later than the quote's, and it is redeemable once. |
{
"type": "object",
"required": [
"order_id",
"connection_id"
],
"properties": {
"dry_run": {
"type": "boolean",
"default": true,
"description": "Default true: report what would change without writing. A live push needs approval: a person's confirmation, or an agent key allowed push_to_crm on this connection."
},
"order_id": {
"type": "string",
"pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
],
"description": "The order whose records to push."
},
"connection_id": {
"type": "string",
"pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
],
"description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G."
},
"update_existing": {
"type": "boolean",
"default": true,
"description": "Update records already in the CRM, matched on mydatahub_record_id. Default true."
},
"confirmation_token": {
"type": "string",
"maxLength": 2000,
"minLength": 16,
"description": "The token the approval page on mydatahub.emailmovers.com returns once the signed-in person approves. It is bound to that person (their sub), this spend (the machine quote_id, or the enrichment or push) and an expiry no later than the quote's, and it is redeemable once."
}
},
"additionalProperties": false
}Creates a machine quote for a count: the records you would receive after removing ones already held and suppressed, the credits and GBP price, the licence, the warranty and any blockers. The quote_id lasts 24 hours and is bound to the dataset version; it is not a human sales quote, which is a 14 day PDF made in the app. Free and needs no account, and nothing is charged. Show the credits and price to the user, then call create_order with the quote_id. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Records to buy; left out, the whole count. |
| licence | string | multi_use_12m (12 month multi-use, every plan) or outright (1.8 credits a record, proposed). |
| count_id* | string | A count id from POST /v1/counts or count_audience. Either case is accepted; responses use upper case. |
| field_set* | string | A field set id from GET /v1/field-sets, such as standard. |
| connection_id | string | The CRM connection to check, only with dedupe_against crm or previous_orders_and_crm. |
| dedupe_against | string | Remove records you already hold: from earlier orders, from a connected CRM, or both. Default previous_orders when signed in. crm and previous_orders_and_crm need connection_id. |
{
"type": "object",
"allOf": [
{
"if": {
"type": "object",
"required": [
"dedupe_against"
],
"properties": {
"dedupe_against": {
"enum": [
"crm",
"previous_orders_and_crm"
]
}
}
},
"then": {
"type": "object",
"required": [
"connection_id"
],
"properties": {
"connection_id": true
}
}
},
{
"if": {
"type": "object",
"required": [
"connection_id"
],
"properties": {
"connection_id": true
}
},
"then": {
"type": "object",
"required": [
"dedupe_against"
],
"properties": {
"dedupe_against": {
"enum": [
"crm",
"previous_orders_and_crm"
]
}
}
}
}
],
"required": [
"count_id",
"field_set"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 1000000,
"minimum": 1,
"description": "Records to buy; left out, the whole count."
},
"licence": {
"enum": [
"multi_use_12m",
"outright"
],
"type": "string",
"default": "multi_use_12m",
"description": "multi_use_12m (12 month multi-use, every plan) or outright (1.8 credits a record, proposed)."
},
"count_id": {
"type": "string",
"pattern": "^cnt_[A-Za-z2-7]{20}$",
"examples": [
"cnt_7K2PQ4MAXN3R6TBY5WDZ"
],
"description": "A count id from POST /v1/counts or count_audience. Either case is accepted; responses use upper case."
},
"field_set": {
"type": "string",
"pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
"description": "A field set id from GET /v1/field-sets, such as standard."
},
"connection_id": {
"type": "string",
"pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
],
"description": "The CRM connection to check, only with dedupe_against crm or previous_orders_and_crm."
},
"dedupe_against": {
"enum": [
"none",
"previous_orders",
"crm",
"previous_orders_and_crm"
],
"type": "string",
"default": "previous_orders",
"description": "Remove records you already hold: from earlier orders, from a connected CRM, or both. Default previous_orders when signed in. crm and previous_orders_and_crm need connection_id."
}
},
"description": "What to price: a count, a field set, how many records and the licence. Free, and needs no account.",
"additionalProperties": false
}Records an objection to direct marketing for one record, by record id or email hash. Scope licensee suppresses it for your organisation at once; scope emailmovers suppresses it database-wide within one working day and tells every licensee holding it. Free; it needs suppressions:write, and repeating the same objection returns the same suppression. Call it whenever a contact objects, in any channel. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| note | string | |
| scope* | string | licensee suppresses the record for your organisation at once; emailmovers suppresses it database-wide within one working day. |
| channel* | string | |
| record_id | string | Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8. |
| received_at* | string | RFC 3339 date and time, with Z or an offset such as +01:00. |
| email_sha256 | string | SHA-256 of the trimmed, lower cased address, when the record id is not known. |
{
"type": "object",
"oneOf": [
{
"type": "object",
"required": [
"record_id"
],
"properties": {
"record_id": true
}
},
{
"type": "object",
"required": [
"email_sha256"
],
"properties": {
"email_sha256": true
}
}
],
"required": [
"channel",
"received_at",
"scope"
],
"properties": {
"note": {
"type": "string",
"maxLength": 2000
},
"scope": {
"enum": [
"licensee",
"emailmovers"
],
"type": "string",
"description": "licensee suppresses the record for your organisation at once; emailmovers suppresses it database-wide within one working day."
},
"channel": {
"enum": [
"email",
"telephone",
"post",
"web_form",
"other"
],
"type": "string"
},
"record_id": {
"type": "string",
"pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
],
"description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8."
},
"received_at": {
"type": "string",
"format": "date-time",
"description": "RFC 3339 date and time, with Z or an offset such as +01:00."
},
"email_sha256": {
"type": "string",
"pattern": "^[0-9a-f]{64}$",
"description": "SHA-256 of the trimmed, lower cased address, when the record id is not known."
}
},
"description": "An objection to direct marketing, to record and propagate: exactly one of record_id or email_sha256.",
"additionalProperties": false
}Turns free text such as 20 miles of Leeds, Yorkshire or LS1 into region, county, town, postcode or radius filters, each with a count and a ready filter. Ambiguous places come back as candidates with a question, so ask the user which they meant rather than choosing. Free and needs no account, though a radius under 5 miles needs an account. Add the chosen filter to the audience, then call count_audience. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| text* | string | Free text such as "20 miles of Leeds", "Yorkshire" or "SW1". |
| dataset | string | The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served. |
| radius_miles | number |
{
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Free text such as \"20 miles of Leeds\", \"Yorkshire\" or \"SW1\"."
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
},
"radius_miles": {
"type": "number",
"maximum": 100,
"minimum": 1
}
},
"description": "A place to resolve into geography filters.",
"additionalProperties": false
}Saves an audience definition under a name, shared across the organisation, or updates a saved one when audience_id is given. Use it when the user wants to keep, share or recount a list later; saving is free and needs audiences:write. Repeating the same call returns the same saved audience. Call list_audiences to find it again, or count_audience with its aud_ id. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| brief | any | |
| audience | any | |
| audience_id | string | A saved audience to update. Leave it out to save a new one. |
{
"type": "object",
"$defs": {
"Filter": {
"oneOf": [
{
"$ref": "#/$defs/InFilter"
},
{
"$ref": "#/$defs/BetweenFilter"
},
{
"$ref": "#/$defs/GteFilter"
},
{
"$ref": "#/$defs/LteFilter"
},
{
"$ref": "#/$defs/MatchesFilter"
},
{
"$ref": "#/$defs/WithinRadiusFilter"
},
{
"$ref": "#/$defs/InListFilter"
},
{
"$ref": "#/$defs/SinceFilter"
}
],
"description": "One criterion: a field from GET /v1/catalogue/filters, an operator and its operands. Exclusions nest under not."
},
"AllGroup": {
"type": "object",
"required": [
"all"
],
"properties": {
"all": {
"type": "array",
"items": {
"$ref": "#/$defs/WhereNode"
},
"minItems": 1
}
},
"description": "AND: every node inside must match.",
"additionalProperties": false
},
"AnyGroup": {
"type": "object",
"required": [
"any"
],
"properties": {
"any": {
"type": "array",
"items": {
"$ref": "#/$defs/WhereNode"
},
"minItems": 1
}
},
"description": "OR: at least one node inside must match.",
"additionalProperties": false
},
"Audience": {
"type": "object",
"title": "MyDataHub audience definition (mydatahub.audience/1)",
"required": [
"schema"
],
"properties": {
"where": {
"$ref": "#/$defs/WhereNode",
"description": "The filters. Left out, the audience is the whole dataset after the defaults."
},
"dedupe": {
"enum": [
"none",
"one_per_company",
"one_per_site"
],
"type": "string",
"description": "none keeps every matching contact, one_per_company keeps one contact per company, one_per_site keeps one per site. Default none."
},
"schema": {
"type": "string",
"const": "mydatahub.audience/1",
"description": "The definition's namespace and version. Older versions are upgraded by a pure function."
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
},
"email_policy": {
"$ref": "#/$defs/EmailPolicy"
},
"dataset_version": {
"type": "string",
"pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
"examples": [
"2026-W39"
],
"description": "The weekly build to count against, such as 2026-W39. Left out, the current version is filled in and returned."
}
},
"description": "Who you want, as filters grouped by entity (company., site., contact., email., phone., signal.). The server fills its defaults (active companies, named emails, corporate subscribers, the current dataset_version) and returns the effective definition with every count.",
"additionalProperties": false
},
"InFilter": {
"type": "object",
"examples": [
{
"op": "in",
"field": "company.sic_2007",
"values": [
"C"
]
}
],
"required": [
"field",
"op",
"values"
],
"properties": {
"op": {
"type": "string",
"const": "in"
},
"field": {
"enum": [
"company.sic_2007",
"company.business_class",
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"company.type",
"company.status",
"company.subscriber_class",
"company.companies_house_number",
"site.region",
"site.county",
"site.town",
"site.postcode",
"contact.title_family",
"contact.job_function",
"contact.job_level_rank",
"contact.premium",
"email.exists",
"email.type",
"phone.exists",
"phone.tps_ctps_status"
],
"type": "string"
},
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
},
{
"type": "boolean"
}
],
"description": "A code, a rank or a boolean, as the field's catalogue lists it."
},
"maxItems": 10000,
"minItems": 1
}
},
"description": "The field holds one of the listed codes.",
"additionalProperties": false
},
"NotGroup": {
"type": "object",
"required": [
"not"
],
"properties": {
"not": {
"$ref": "#/$defs/WhereNode"
}
},
"description": "Negation: the single node inside must not match.",
"additionalProperties": false
},
"GteFilter": {
"type": "object",
"examples": [
{
"op": "gte",
"field": "company.employee_band",
"value": "50-99"
}
],
"required": [
"field",
"op",
"value"
],
"properties": {
"op": {
"type": "string",
"const": "gte"
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"email.deliverability_score"
],
"type": "string"
},
"value": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
}
},
"description": "The field is at or after the value in its order: for bands, the band and every larger one.",
"additionalProperties": false
},
"LteFilter": {
"type": "object",
"examples": [
{
"op": "lte",
"field": "contact.job_level_rank",
"value": 6
}
],
"required": [
"field",
"op",
"value"
],
"properties": {
"op": {
"type": "string",
"const": "lte"
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"contact.company_contact_rank",
"email.deliverability_score"
],
"type": "string"
},
"value": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
}
},
"description": "The field is at or before the value in its order. Rank 1 is the most senior, so Director and above is contact.job_level_rank lte 6.",
"additionalProperties": false
},
"WhereNode": {
"anyOf": [
{
"$ref": "#/$defs/AllGroup"
},
{
"$ref": "#/$defs/AnyGroup"
},
{
"$ref": "#/$defs/NotGroup"
},
{
"$ref": "#/$defs/BundleNode"
},
{
"$ref": "#/$defs/Filter"
}
],
"description": "A group (all, any, not), a title bundle or a filter. Groups nest up to 32 deep, and a where tree holds up to 1,000 filters, groups and bundles."
},
"BundleNode": {
"type": "object",
"required": [
"bundle"
],
"properties": {
"bundle": {
"enum": [
"sdm",
"manager_and_above",
"owner_managed"
],
"type": "string"
}
},
"description": "A title bundle, resolved to its filters in the effective definition: sdm (senior decision makers), manager_and_above (managers and above), owner_managed (owner managed).",
"additionalProperties": false
},
"EmailPolicy": {
"type": "object",
"properties": {
"allow_catch_all": {
"type": "boolean",
"description": "Whether catch-all addresses count. Default false."
},
"min_deliverability_score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Lowest deliverability score counted, 0 to 100. Default 70."
}
},
"description": "Email quality floor. Defaults: min_deliverability_score 70, allow_catch_all false.",
"additionalProperties": false
},
"PlaceCentre": {
"type": "object",
"required": [
"place"
],
"properties": {
"code": {
"type": "string",
"maxLength": 20,
"minLength": 1,
"description": "The ONS geography code of the chosen candidate when resolve_location found more than one, such as E08000035 for the Leeds district."
},
"place": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "A place name, resolved with resolve_location, such as Leeds."
}
},
"description": "A named place. Ambiguous names come back from resolve_location as candidates, never a silent choice.",
"additionalProperties": false
},
"PointCentre": {
"type": "object",
"required": [
"lat",
"lon"
],
"properties": {
"lat": {
"type": "number",
"maximum": 61,
"minimum": 49
},
"lon": {
"type": "number",
"maximum": 2,
"minimum": -9
}
},
"description": "A latitude and longitude in WGS84 degrees.",
"additionalProperties": false
},
"SinceFilter": {
"type": "object",
"examples": [
{
"op": "since",
"days": 90,
"field": "signal.type",
"values": [
"company.incorporated"
]
}
],
"required": [
"field",
"op",
"days"
],
"properties": {
"op": {
"type": "string",
"const": "since"
},
"days": {
"type": "integer",
"maximum": 3650,
"minimum": 1
},
"field": {
"enum": [
"contact.last_validated_at",
"email.last_verified_at",
"signal.type",
"signal.observed_at"
],
"type": "string"
},
"values": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 10000,
"minItems": 1,
"description": "For signal.type only: the signal types to look for, such as company.incorporated."
}
},
"description": "Within the last N days: a date field, or a Companies House signal of the listed types on signal.type.",
"additionalProperties": false
},
"InListFilter": {
"type": "object",
"examples": [
{
"op": "in_list",
"field": "email.address_sha256",
"list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
}
],
"required": [
"field",
"op",
"list_id"
],
"properties": {
"op": {
"type": "string",
"const": "in_list"
},
"field": {
"enum": [
"company.companies_house_number",
"contact.title",
"email.address_sha256",
"email.domain_sha256",
"phone.e164_sha256"
],
"type": "string"
},
"list_id": {
"type": "string",
"pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
],
"description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA."
}
},
"description": "The record's hashed email, domain, phone, company number or title term is on a suppression list. Usually nested under not; each list reports the records it removed.",
"additionalProperties": false
},
"RadiusCentre": {
"anyOf": [
{
"$ref": "#/$defs/PlaceCentre"
},
{
"$ref": "#/$defs/PostcodeCentre"
},
{
"$ref": "#/$defs/PointCentre"
}
],
"description": "The centre of a radius: a place, a postcode or a latitude and longitude."
},
"BetweenFilter": {
"type": "object",
"examples": [
{
"op": "between",
"to": "200-349",
"from": "10-19",
"field": "company.employee_band"
}
],
"required": [
"field",
"op",
"from",
"to"
],
"properties": {
"op": {
"type": "string",
"const": "between"
},
"to": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
},
"from": {
"anyOf": [
{
"type": "string",
"maxLength": 200,
"minLength": 1
},
{
"type": "number"
}
],
"description": "A band code or a number from the field's order."
},
"field": {
"enum": [
"company.employee_band",
"company.turnover_band",
"company.fleet_band",
"contact.job_level_rank",
"email.deliverability_score"
],
"type": "string"
}
},
"description": "The field lies from one value to another inclusive, over the field's order.",
"additionalProperties": false
},
"MatchesFilter": {
"type": "object",
"allOf": [
{
"if": {
"type": "object",
"required": [
"mode"
],
"properties": {
"mode": {
"const": "exact"
}
}
},
"then": {
"type": "object",
"properties": {
"expand": {
"type": "array",
"maxItems": 0
},
"exclude_terms": {
"type": "array",
"maxItems": 0
}
}
}
}
],
"examples": [
{
"op": "matches",
"mode": "contains",
"field": "contact.title",
"terms": [
"marketing manager"
],
"expand": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations"
]
}
],
"required": [
"field",
"op",
"terms"
],
"properties": {
"op": {
"type": "string",
"const": "matches"
},
"mode": {
"enum": [
"contains",
"starts_with",
"exact"
],
"type": "string",
"description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
},
"field": {
"enum": [
"contact.title"
],
"type": "string"
},
"terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"minItems": 1
},
"expand": {
"type": "array",
"items": {
"enum": [
"plural_singular",
"department_synonyms",
"ampersand_and",
"abbreviations",
"permutations"
],
"type": "string"
},
"maxItems": 5,
"description": "Expansion sets to apply, each once: plural_singular, department_synonyms, ampersand_and, abbreviations, permutations. Left out, the first four apply; an empty list applies none. Not used with mode exact.",
"uniqueItems": true
},
"exclude_terms": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Expanded terms removed by hand. Kept in the definition so the count stays reproducible when the title dictionary changes."
}
},
"description": "Job title keyword match. mode contains (the default) or starts_with expands each term with the expansion sets; mode exact matches verbatim titles. Every expanded term is returned with the count.",
"additionalProperties": false
},
"PostcodeCentre": {
"type": "object",
"required": [
"postcode"
],
"properties": {
"postcode": {
"type": "string",
"pattern": "^[A-Za-z]{1,2}([0-9][0-9A-Za-z]?( [0-9]([A-Za-z]{2})?| ?[0-9][A-Za-z]{2})?)?$",
"description": "The centroid of a postcode unit, sector, district or area, such as LS1 4AP."
}
},
"description": "A postcode centroid from ONSPD.",
"additionalProperties": false
},
"WithinRadiusFilter": {
"type": "object",
"examples": [
{
"op": "within_radius",
"field": "site.location",
"centre": {
"place": "Leeds"
},
"radius_miles": 20
}
],
"required": [
"field",
"op",
"centre",
"radius_miles"
],
"properties": {
"op": {
"type": "string",
"const": "within_radius"
},
"field": {
"enum": [
"site.location"
],
"type": "string"
},
"centre": {
"$ref": "#/$defs/RadiusCentre"
},
"radius_miles": {
"type": "number",
"maximum": 100,
"minimum": 1,
"description": "Radius in miles, 1 to 100. Under 5 miles needs an account."
}
},
"description": "Sites within radius_miles of the centre. The count reports the centroid used and the postcodes matched.",
"additionalProperties": false
}
},
"anyOf": [
{
"not": {
"type": "object",
"required": [
"audience_id"
],
"properties": {
"audience_id": true
}
},
"type": "object",
"required": [
"name",
"audience"
],
"properties": {
"name": true,
"brief": {
"type": "string"
},
"audience": true
}
},
{
"type": "object",
"anyOf": [
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": true
}
},
{
"type": "object",
"required": [
"audience"
],
"properties": {
"audience": true
}
},
{
"type": "object",
"required": [
"brief"
],
"properties": {
"brief": true
}
}
],
"required": [
"audience_id"
],
"properties": {
"audience_id": true
}
}
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"brief": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
]
},
"audience": {
"$ref": "#/$defs/Audience"
},
"audience_id": {
"type": "string",
"pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
"examples": [
"aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
],
"description": "A saved audience to update. Leave it out to save a new one."
}
},
"description": "Save a new audience (name and audience, brief optional) or update one (audience_id and at least one of name, audience or brief).",
"additionalProperties": false
}Deprecated: saves the filters held in the server session under a name. Use save_audience instead. It saves an audience definition shared across the organisation; saved lists carry over as audiences (aud_). It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Deprecated: searches the values of one filter category. Use search_filter_values instead. It returns codes with counts and did_you_mean for near misses. It stops working 12 months after the new tools launch, after three emailed notices; https://emailmovers.com/mydatahub/docs/migrate maps every call. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
No arguments.
{
"type": "object",
"properties": {},
"description": "The arguments of the old tool, unchanged during the deprecation window. The adapter maps them to the new tools; emailmovers.com/mydatahub/docs/migrate lists them.",
"additionalProperties": {}
}Searches the values of one field by text, such as towns matching leeds, and returns each code with its contact and company counts plus did_you_mean for near misses. Use the returned code in a filter rather than guessing one. Free and needs no account; results are paged with next_cursor. Call count_audience once the filters are chosen. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.
| Argument | Type | Description |
|---|---|---|
| q | string | Text to search for. |
| limit | integer | Items per page, 1 to 100. Default 25. |
| cursor | string | An opaque cursor from next_cursor. Pass it back unchanged. |
| dataset | string | The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served. |
| dimension* | string | A field name from list_filters, such as site.town or company.sic_2007. |
{
"type": "object",
"required": [
"dimension"
],
"properties": {
"q": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "Text to search for."
},
"limit": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Items per page, 1 to 100. Default 25."
},
"cursor": {
"type": "string",
"maxLength": 512,
"minLength": 1,
"description": "An opaque cursor from next_cursor. Pass it back unchanged."
},
"dataset": {
"enum": [
"uk_contacts",
"ie_contacts",
"global_contacts"
],
"type": "string",
"description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
},
"dimension": {
"type": "string",
"pattern": "^(company|site|contact|email|phone|signal)\\.[a-z0-9_]+$",
"description": "A field name from list_filters, such as site.town or company.sic_2007."
}
},
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 9, 2026.