{
  "openapi": "3.1.1",
  "info": {
    "title": "MyDataHub API",
    "version": "2.0.0",
    "summary": "UK B2B contact counts, quotes and lists, by Emailmovers.",
    "description": "MyDataHub by Emailmovers, the UK B2B count engine. Looking is free: the catalogue, counts, breakdowns, masked previews, machine quotes and plans need no account. One credit buys one complete UK record at the same price here, in the app and in the MCP server at https://mydatahub.emailmovers.com/mcp.\n\nEvery spend follows a signed machine quote (24 hours) and a human confirmation or a pre-authorised agent key; a confirmed flag set by a model is never consent, and a standard API key or OAuth token alone never spends. x-cost-credits on every operation gives its credit cost, and x-free marks the free ones.\n\nErrors are RFC 9457 problem details with next_step and did_you_mean. Rate limits use the IETF RateLimit and RateLimit-Policy fields, with Retry-After on 429 and 503. Lists return {data, has_more, next_cursor}. Response objects may gain members in a later MyDataHub-Version: ignore members you do not know.",
    "contact": {
      "name": "MyDataHub by Emailmovers Ltd",
      "url": "https://emailmovers.com/mydatahub/docs"
    },
    "license": {
      "name": "MyDataHub Data Licence and Sharing Agreement (terms version 2026-09)",
      "url": "https://mydatahub.emailmovers.com/licence.json"
    },
    "x-mydatahub-version": "2027-01-15"
  },
  "servers": [
    {
      "url": "https://mydatahub.emailmovers.com/v1",
      "description": "Production. Test keys (mdh_test_) return synthetic data and never charge."
    }
  ],
  "security": [
    {
      "OAuth2": []
    },
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Catalogue",
      "description": "Free and public: plans, datasets, filter fields and values, field sets, title expansion, location resolution and compiling a brief."
    },
    {
      "name": "Counts",
      "description": "Free and public: counts with breakdowns, and masked samples (previews)."
    },
    {
      "name": "Samples",
      "description": "A sample of a counted audience, sent only after a person confirms a work email address, and downloaded once."
    },
    {
      "name": "Audiences",
      "description": "Saved audiences shared across the organisation."
    },
    {
      "name": "Quotes",
      "description": "Machine quotes (24 hours, free and public) and human sales quotes (14 days)."
    },
    {
      "name": "Orders",
      "description": "Spend credits against a machine quote; status, cancellation and the signed compliance receipt."
    },
    {
      "name": "Records",
      "description": "Delivered records under licence, as pages or a signed download. Free."
    },
    {
      "name": "Lookups",
      "description": "Company lookup (free) and contact enrichment (1 credit on a confident match)."
    },
    {
      "name": "Suppressions",
      "description": "Suppression lists, checks before a send, and objections."
    },
    {
      "name": "Compliance",
      "description": "Public: the trust document, the LIA and compliance receipt verification."
    },
    {
      "name": "Account",
      "description": "Balance, plan, usage, credits bought by card, and ending a rolling plan."
    },
    {
      "name": "Keys",
      "description": "API keys and agent keys with budgets."
    },
    {
      "name": "CRM push",
      "description": "CRM connections, the New to you overlap check and record pushes."
    },
    {
      "name": "Webhooks",
      "description": "Webhook endpoints and the 30 day event log."
    },
    {
      "name": "Meta",
      "description": "This document and the health check."
    }
  ],
  "externalDocs": {
    "description": "Guides and the MCP server",
    "url": "https://emailmovers.com/mydatahub/docs"
  },
  "x-rate-limits": [
    {
      "tier": "anonymous",
      "counts": "60 an hour and 600 a day per IP and fingerprint",
      "other": "Challenge after 20; at most 6 filters an audience; no single company counts, free text title search or radius under 5 miles; counts under 100 and breakdown cells rounded to the nearest 5",
      "status": "confirmed"
    },
    {
      "tier": "free",
      "counts": "60 a minute and 1,000 a day per organisation",
      "other": "Counts under 100 and breakdown cells rounded to the nearest 5",
      "status": "to_confirm"
    },
    {
      "tier": "paid",
      "counts": "Published per plan",
      "other": "Exact counts",
      "status": "confirmed"
    }
  ],
  "paths": {
    "/plans": {
      "get": {
        "operationId": "getPlans",
        "summary": "Get plans and prices",
        "description": "Plans, credit packs, credit rules, licence terms, the guarantee and the free trial, in GBP excluding VAT. The same content as https://mydatahub.emailmovers.com/pricing.json. One credit buys one complete UK record at the same price in the app, API and MCP server.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Plans and prices.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pricing"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Today's plans and credit packs",
                    "value": {
                      "version": "2026-10",
                      "valid_from": "2026-10-13",
                      "currency": "GBP",
                      "vat_treatment": "Prices exclude VAT at 20 percent.",
                      "credit_definition": "1 credit buys 1 complete UK record, delivered once, at the per-contact scale's rate, the same in the app, API and MCP server.",
                      "price_scale": {
                        "id": "per_contact_scale",
                        "name": "Per-contact scale",
                        "status": "confirmed",
                        "available_to": "everyone",
                        "minimum_order_records": 0,
                        "rule": "The credits bought, after any balance, pick one band, and every credit in the purchase is at its rate. A quote compares the scale with the credit pack and leads with the cheaper.",
                        "bands": [
                          {
                            "from_records": 1,
                            "to_records": 2999,
                            "gbp_per_record": 0.25
                          },
                          {
                            "from_records": 3000,
                            "to_records": 9999,
                            "gbp_per_record": 0.25
                          },
                          {
                            "from_records": 10000,
                            "to_records": 24999,
                            "gbp_per_record": 0.22
                          },
                          {
                            "from_records": 25000,
                            "to_records": 49999,
                            "gbp_per_record": 0.195
                          },
                          {
                            "from_records": 50000,
                            "to_records": null,
                            "gbp_per_record": 0.17
                          }
                        ]
                      },
                      "plans": [
                        {
                          "id": "free",
                          "name": "Free",
                          "kind": "free",
                          "status": "confirmed",
                          "available_to": "everyone",
                          "price_gbp_ex_vat": 0,
                          "billing_period": "once",
                          "credits": 100,
                          "per_record_gbp": null,
                          "credits_expire": false,
                          "for_whom": "Triallists, human or agent",
                          "notes": "No card"
                        },
                        {
                          "id": "pay_as_you_go",
                          "name": "Pay as you go",
                          "kind": "subscription",
                          "status": "confirmed",
                          "available_to": "existing_customers",
                          "price_gbp_ex_vat": 299,
                          "billing_period": "month",
                          "credits": 1000,
                          "per_record_gbp": 0.299,
                          "rollover_cap_credits": 12000,
                          "credits_expire": false,
                          "for_whom": "Existing customers, who keep this price",
                          "notes": "Cancel any time. Not sold to new customers since 13 October 2026."
                        },
                        {
                          "id": "plan_12_month",
                          "name": "12-month plan",
                          "kind": "subscription",
                          "status": "confirmed",
                          "available_to": "existing_customers",
                          "price_gbp_ex_vat": 249,
                          "billing_period": "month",
                          "annual_price_gbp_ex_vat": 2988,
                          "credits": 1000,
                          "per_record_gbp": 0.249,
                          "rollover_cap_credits": 12000,
                          "credits_expire": false,
                          "for_whom": "Existing customers, who keep this price",
                          "notes": "Not sold to new customers since 13 October 2026."
                        },
                        {
                          "id": "subscription_2000",
                          "name": "Subscription",
                          "kind": "subscription",
                          "status": "confirmed",
                          "available_to": "new_customers",
                          "price_gbp_ex_vat": 500,
                          "billing_period": "month",
                          "contract_months": 12,
                          "annual_price_gbp_ex_vat": 6000,
                          "credits": 2000,
                          "per_record_gbp": 0.25,
                          "rollover_cap_credits": 0,
                          "credits_expire": true,
                          "for_whom": "Teams that buy every month",
                          "notes": "A 12-month contract. Each month's 2,000 records are used or lost; records beyond them cost the quote's cheapest purchase."
                        }
                      ],
                      "credit_packs": [
                        {
                          "id": "credit_pack_40000",
                          "name": "Credit pack 40,000",
                          "kind": "pack",
                          "status": "confirmed",
                          "available_to": "everyone",
                          "price_gbp_ex_vat": 1249,
                          "billing_period": "once",
                          "credits": 40000,
                          "per_record_gbp": 0.031,
                          "credits_expire": false,
                          "for_whom": "Anyone buying about 5,000 records or more"
                        }
                      ],
                      "credit_rules": [
                        {
                          "action": "count",
                          "label": "Count, breakdown, preview, machine quote, catalogue, title expansion",
                          "credits": 0,
                          "unit": "call",
                          "status": "confirmed"
                        },
                        {
                          "action": "record",
                          "label": "Full UK contact record delivered, any channel or field set",
                          "credits": 1,
                          "unit": "record",
                          "status": "confirmed"
                        },
                        {
                          "action": "company_only_record",
                          "label": "Company-only record (no named contact)",
                          "credits": 0.1,
                          "unit": "record",
                          "status": "proposed"
                        },
                        {
                          "action": "enrich_contact",
                          "label": "Contact enrichment, match found",
                          "credits": 1,
                          "unit": "match",
                          "status": "confirmed",
                          "note": "0 if already licensed"
                        },
                        {
                          "action": "lookup_company",
                          "label": "Company lookup, no contact details",
                          "credits": 0,
                          "unit": "call",
                          "status": "to_confirm"
                        },
                        {
                          "action": "outright",
                          "label": "Outright ownership",
                          "credits": 1.8,
                          "unit": "record",
                          "status": "proposed"
                        }
                      ],
                      "licence": [
                        {
                          "licence_type": "multi_use_12m",
                          "status": "confirmed",
                          "credits_per_record": 1,
                          "permitted_channels": [
                            "email",
                            "telephone",
                            "post"
                          ],
                          "reuse_months": 12,
                          "resale_prohibited": true,
                          "warranty_url": "https://emailmovers.com/trust/warranty",
                          "terms_version": "2026-09"
                        }
                      ],
                      "guarantee": {
                        "current": {
                          "policy": "replace_over_threshold_hard_bounce",
                          "threshold_percent": 10,
                          "url": "https://emailmovers.com/trust/warranty"
                        },
                        "proposed": {
                          "policy": "replace_any_hard_bounce_30d",
                          "url": "https://emailmovers.com/trust/warranty"
                        },
                        "refunds": [
                          "Credits and credit packs are not refundable once bought, except where the law requires.",
                          "Existing customers keep what their signed agreement says until it renews."
                        ]
                      },
                      "trial": {
                        "credits": 100,
                        "card_required": false,
                        "expires": false
                      },
                      "meters": [
                        {
                          "action": "record",
                          "unit": "record",
                          "credits": 1,
                          "status": "confirmed"
                        },
                        {
                          "action": "enrich_contact",
                          "unit": "match",
                          "credits": 1,
                          "status": "confirmed"
                        },
                        {
                          "action": "company_only_record",
                          "unit": "record",
                          "credits": 0.1,
                          "status": "proposed"
                        },
                        {
                          "action": "outright",
                          "unit": "record",
                          "credits": 1.8,
                          "status": "proposed"
                        },
                        {
                          "action": "count",
                          "unit": "call",
                          "credits": 0,
                          "status": "confirmed"
                        }
                      ],
                      "action_path": [
                        {
                          "step": 1,
                          "action": "quote_order",
                          "rest": "POST /v1/quotes",
                          "description": "Get a signed machine quote for a count, valid 24 hours. Free."
                        },
                        {
                          "step": 2,
                          "action": "create_order",
                          "rest": "POST /v1/orders",
                          "description": "Spend credits against the quote_id with a person's confirmation or an agent key within its limits."
                        },
                        {
                          "step": 3,
                          "action": "https://mydatahub.emailmovers.com/billing/top-up",
                          "rest": null,
                          "description": "When the balance is short, buy one of the quote's purchase options (the cheapest comes first) through Stripe Checkout, then retry step 2."
                        }
                      ],
                      "promises": [
                        {
                          "key": "looking_is_free",
                          "statement": "Looking is free forever",
                          "in_practice": "Filters, counts, breakdowns, masked previews, machine quotes, plans and trust documents need no account or card."
                        },
                        {
                          "key": "never_pay_twice",
                          "statement": "Never pay twice",
                          "in_practice": "Re-downloads under licence, duplicates, suppressed records, records you already hold and failed lookups cost 0."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "get_plans"
      }
    },
    "/datasets": {
      "get": {
        "operationId": "listDatasets",
        "summary": "List datasets",
        "description": "Every dataset with owner, source, licence, refresh, residency, regulator, warranty and credits per record. v2.0 serves uk_contacts; the others are listed with their status.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of datasets.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The UK dataset",
                    "value": {
                      "data": [
                        {
                          "id": "uk_contacts",
                          "name": "UK contacts",
                          "status": "live",
                          "owner": "Emailmovers Ltd",
                          "source": "Emailmovers research; Companies House (OGL v3.0); ONSPD (OGL v3.0)",
                          "licence": "12 month multi-use licence; resale prohibited",
                          "refresh": "Immutable weekly build every Monday; same-day suppression overlay",
                          "residency": "Held in the UK (Google Cloud London)",
                          "regulator": "ICO",
                          "warranty": "Replacement when hard bounces exceed 10 percent of an order",
                          "credits_per_record": 1,
                          "credits_status": "confirmed",
                          "current_version": "2026-W39",
                          "versions_available": 52
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/datasets/{dataset}/versions/{version}": {
      "get": {
        "operationId": "getDatasetVersion",
        "summary": "Get a dataset version changelog",
        "description": "What changed in one immutable weekly build: records added, retired and re-verified, companies dissolved, job changes confirmed, suppressions applied, coverage by field and the input snapshots.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "dataset",
            "in": "path",
            "required": true,
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served.",
            "schema": {
              "type": "string",
              "enum": [
                "uk_contacts",
                "ie_contacts",
                "global_contacts"
              ]
            },
            "example": "uk_contacts"
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
              "examples": [
                "2026-W39"
              ]
            },
            "example": "2026-W39"
          }
        ],
        "responses": {
          "200": {
            "description": "The version's changelog.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetVersionChangelog"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The 2026-W39 build",
                    "value": {
                      "dataset": "uk_contacts",
                      "version": "2026-W39",
                      "built_at": "2026-09-21T04:00:00Z",
                      "checksum": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
                      "row_counts": {
                        "companies": 5689369,
                        "sites": 3232415,
                        "contacts": 9028587,
                        "emails": 1660190,
                        "phones": 1210000
                      },
                      "changes": {
                        "records_added": 4120,
                        "records_retired": 1870,
                        "records_reverified": 118400,
                        "companies_dissolved": 15130,
                        "job_changes_confirmed": 210,
                        "suppressions_applied": 96
                      },
                      "coverage_pct": {
                        "named_email": 17.8,
                        "email": 18.4
                      },
                      "input_snapshots": [
                        {
                          "source": "companies_house",
                          "as_of": "2026-09-01"
                        },
                        {
                          "source": "onspd",
                          "as_of": "2026-08-01"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/catalogue/filters": {
      "get": {
        "operationId": "listFilters",
        "summary": "List filter fields",
        "description": "Every filterable field of mydatahub.audience/1 with its group, type, operators, value count and default, plus the operators and the dataset list. Free and public, cached for 24 hours.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "dataset",
            "in": "query",
            "required": false,
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served.",
            "schema": {
              "type": "string",
              "enum": [
                "uk_contacts",
                "ie_contacts",
                "global_contacts"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The filter catalogue.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FilterCatalogue"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Filter catalogue",
                    "value": {
                      "dataset": "uk_contacts",
                      "dataset_version": "2026-W39",
                      "fields": [
                        {
                          "field": "company.employee_band",
                          "group": "company",
                          "type": "band",
                          "label": "Employee band",
                          "description": "Company size in 13 bands, 1-5 to 10000+.",
                          "operators": [
                            "in",
                            "between",
                            "gte",
                            "lte"
                          ],
                          "facet": true,
                          "value_count": 14,
                          "default": null,
                          "examples": [
                            "50-99"
                          ],
                          "values_url": "/v1/catalogue/filters/company.employee_band/values"
                        }
                      ],
                      "operators": [
                        {
                          "op": "gte",
                          "applies_to": "banded and ranked fields",
                          "description": "The value and everything after it in the order (for bands, larger bands)."
                        }
                      ],
                      "datasets": [
                        {
                          "id": "uk_contacts",
                          "name": "UK contacts",
                          "status": "live",
                          "owner": "Emailmovers Ltd",
                          "source": "Emailmovers research; Companies House (OGL v3.0); ONSPD (OGL v3.0)",
                          "licence": "12 month multi-use licence; resale prohibited",
                          "refresh": "Immutable weekly build every Monday; same-day suppression overlay",
                          "residency": "Held in the UK (Google Cloud London)",
                          "regulator": "ICO",
                          "warranty": "Replacement when hard bounces exceed 10 percent of an order",
                          "credits_per_record": 1,
                          "credits_status": "confirmed",
                          "current_version": "2026-W39",
                          "versions_available": 52
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "list_filters"
      }
    },
    "/catalogue/filters/{dimension}/values": {
      "get": {
        "operationId": "searchFilterValues",
        "summary": "Search filter values",
        "description": "Values of one field, searched by text, each with its contact and company count, plus did_you_mean for a near miss. The dimension is the field name, such as site.town.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "dimension",
            "in": "path",
            "required": true,
            "description": "A field name from GET /v1/catalogue/filters, such as site.town.",
            "schema": {
              "type": "string",
              "pattern": "^(company|site|contact|email|phone|signal)\\.[a-z0-9_]+$"
            },
            "example": "site.town"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Text to search for.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "example": "leeds"
          },
          {
            "name": "dataset",
            "in": "query",
            "required": false,
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served.",
            "schema": {
              "type": "string",
              "enum": [
                "uk_contacts",
                "ie_contacts",
                "global_contacts"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of values.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FilterValueList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Towns matching leeds",
                    "value": {
                      "field": "site.town",
                      "dataset_version": "2026-W39",
                      "data": [
                        {
                          "code": "leeds",
                          "label": "Leeds",
                          "contacts": 41210,
                          "companies": 9870,
                          "parent": "west_yorkshire"
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null,
                      "disclosure": {
                        "level": "rounded",
                        "rounded_to": 5,
                        "secondary_suppression": false,
                        "notes": [
                          "Counts under 100 and every breakdown cell are rounded to the nearest 5 for anonymous and trial callers."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "search_filter_values"
      }
    },
    "/field-sets": {
      "get": {
        "operationId": "listFieldSets",
        "summary": "List field sets",
        "description": "The named bundles of fields an order can deliver, with their exact columns. Every field set costs 1 credit a record: no telephone, export or API surcharge.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of field sets.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldSetList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The standard field set",
                    "value": {
                      "data": [
                        {
                          "id": "standard",
                          "name": "Standard",
                          "description": "Named email, postal address and company fields with Companies House number and SIC.",
                          "credits_per_record": 1,
                          "columns": [
                            {
                              "name": "first_name",
                              "description": "First name"
                            },
                            {
                              "name": "email",
                              "description": "Named business email"
                            },
                            {
                              "name": "companies_house_number",
                              "description": "Companies House number"
                            }
                          ]
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "list_field_sets"
      }
    },
    "/job-titles/expand": {
      "post": {
        "operationId": "expandJobTitles",
        "summary": "Expand job titles",
        "description": "Show every title a keyword matches through the expansion sets (plurals, department synonyms, ampersands, abbreviations, word order), each with a count, or what a bundle such as sdm resolves to. Nothing is resolved silently.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TitleExpansionRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Expand marketing manager",
                  "value": {
                    "terms": [
                      "marketing manager"
                    ],
                    "mode": "contains"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The expanded titles.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TitleExpansion"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Expand marketing manager",
                    "value": {
                      "dataset_version": "2026-W39",
                      "mode": "contains",
                      "expand": [
                        "plural_singular",
                        "department_synonyms",
                        "ampersand_and",
                        "abbreviations"
                      ],
                      "terms": [
                        {
                          "term": "Marketing Manager",
                          "from_term": "marketing manager",
                          "expansion_set": "input",
                          "contacts": 6210
                        },
                        {
                          "term": "Marketing Managers",
                          "from_term": "marketing manager",
                          "expansion_set": "plural_singular",
                          "contacts": 14
                        },
                        {
                          "term": "Mktg Manager",
                          "from_term": "marketing manager",
                          "expansion_set": "abbreviations",
                          "contacts": "under 10"
                        }
                      ],
                      "total_contacts": 6230,
                      "bundle": null,
                      "filter": {
                        "field": "contact.title",
                        "op": "matches",
                        "terms": [
                          "marketing manager"
                        ],
                        "mode": "contains",
                        "expand": [
                          "plural_singular",
                          "department_synonyms",
                          "ampersand_and",
                          "abbreviations"
                        ]
                      },
                      "disclosure": {
                        "level": "rounded",
                        "rounded_to": 5,
                        "secondary_suppression": false,
                        "notes": [
                          "Counts under 100 and every breakdown cell are rounded to the nearest 5 for anonymous and trial callers."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "expand_job_titles"
      }
    },
    "/locations/resolve": {
      "post": {
        "operationId": "resolveLocation",
        "summary": "Resolve a location",
        "description": "Turn free text into region, county, town, postcode or radius filters. Ambiguous names come back as candidates with a question, never a silent choice. A radius under 5 miles needs an account (401 account-required).",
        "tags": [
          "Catalogue"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "counts:read"
            ]
          },
          {
            "ApiKey": [
              "counts:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocationRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Twenty miles of Leeds",
                  "value": {
                    "text": "20 miles of Leeds"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Candidates for the place.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResolution"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Twenty miles of Leeds",
                    "value": {
                      "text": "20 miles of Leeds",
                      "ambiguous": true,
                      "question": "Leeds: city centre or the metropolitan district?",
                      "candidates": [
                        {
                          "kind": "radius",
                          "code": "E08000035",
                          "label": "Within 20 miles of Leeds (metropolitan district centroid)",
                          "contacts": 42318,
                          "centre": {
                            "lat": 53.7997,
                            "lon": -1.5492
                          },
                          "filter": {
                            "field": "site.location",
                            "op": "within_radius",
                            "centre": {
                              "place": "Leeds",
                              "code": "E08000035"
                            },
                            "radius_miles": 20
                          }
                        },
                        {
                          "kind": "radius",
                          "code": "LS1",
                          "label": "Within 20 miles of Leeds city centre (LS1)",
                          "contacts": 41960,
                          "centre": {
                            "lat": 53.7974,
                            "lon": -1.5438
                          },
                          "filter": {
                            "field": "site.location",
                            "op": "within_radius",
                            "centre": {
                              "postcode": "LS1"
                            },
                            "radius_miles": 20
                          }
                        }
                      ],
                      "disclosure": {
                        "level": "rounded",
                        "rounded_to": 5,
                        "secondary_suppression": false,
                        "notes": [
                          "Counts under 100 and every breakdown cell are rounded to the nearest 5 for anonymous and trial callers."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "resolve_location"
      }
    },
    "/audiences/compile": {
      "post": {
        "operationId": "compileAudience",
        "summary": "Compile a brief",
        "description": "Turn a plain English brief into an audience definition with a one-sentence readback, the chips it made and any questions to answer first. Words that match no filter are returned, not guessed.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BriefRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Finance directors at law firms in Manchester",
                  "value": {
                    "brief": "300 finance directors at law firms in Manchester"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The compiled audience.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompiledBrief"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Finance directors at law firms in Manchester",
                    "value": {
                      "audience": {
                        "schema": "mydatahub.audience/1",
                        "dataset": "uk_contacts",
                        "where": {
                          "all": [
                            {
                              "field": "contact.title",
                              "op": "matches",
                              "terms": [
                                "finance director"
                              ]
                            },
                            {
                              "field": "company.sic_2007",
                              "op": "in",
                              "values": [
                                "69102"
                              ]
                            },
                            {
                              "field": "site.town",
                              "op": "in",
                              "values": [
                                "manchester"
                              ]
                            }
                          ]
                        }
                      },
                      "readback": "Finance directors at solicitors (SIC 69102) in Manchester.",
                      "chips": [
                        {
                          "label": "Job title: finance director plus expansions",
                          "pointer": "/where/all/0",
                          "from_brief": "finance directors"
                        },
                        {
                          "label": "Industry: solicitors (SIC 69102)",
                          "pointer": "/where/all/1",
                          "from_brief": "law firms"
                        },
                        {
                          "label": "Town: Manchester",
                          "pointer": "/where/all/2",
                          "from_brief": "in Manchester"
                        }
                      ],
                      "questions": [],
                      "unrecognised": [],
                      "quantity": 300
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "compile_audience"
      }
    },
    "/counts": {
      "post": {
        "operationId": "createCount",
        "summary": "Count an audience",
        "description": "Count an audience, inline or by aud_ id, at contact or company level with up to three breakdown fields. Returns Total, New to you (signed in) and Emailable with companies, breakdowns, quality, the compliance summary, a price estimate and a content-addressed count id (also the ETag). Free, and needs no account; anonymous and trial callers see counts under 100 and every breakdown cell rounded to the nearest 5. Lawful basis for named work emails is UK GDPR Article 6(1)(f) legitimate interests; sole traders and ordinary partnerships are individual subscribers and are left out of email audiences by default.",
        "tags": [
          "Counts"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "counts:read"
            ]
          },
          {
            "ApiKey": [
              "counts:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CountRequest"
              },
              "examples": {
                "spec": {
                  "summary": "Marketing managers and above at manufacturers within 20 miles of Leeds",
                  "value": {
                    "audience": {
                      "schema": "mydatahub.audience/1",
                      "dataset": "uk_contacts",
                      "where": {
                        "all": [
                          {
                            "field": "contact.title",
                            "op": "matches",
                            "terms": [
                              "marketing manager"
                            ],
                            "mode": "contains"
                          },
                          {
                            "field": "contact.job_level_rank",
                            "op": "in",
                            "values": [
                              1,
                              2,
                              3,
                              4,
                              5,
                              6,
                              8,
                              9
                            ]
                          },
                          {
                            "field": "company.sic_2007",
                            "op": "in",
                            "values": [
                              "C"
                            ]
                          },
                          {
                            "field": "company.employee_band",
                            "op": "gte",
                            "value": "50-99"
                          },
                          {
                            "field": "site.location",
                            "op": "within_radius",
                            "centre": {
                              "place": "Leeds"
                            },
                            "radius_miles": 20
                          },
                          {
                            "not": {
                              "field": "email.address_sha256",
                              "op": "in_list",
                              "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                            }
                          }
                        ]
                      }
                    },
                    "level": "contact",
                    "breakdown_by": [
                      "contact.job_level_rank"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The count.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Count"
                },
                "examples": {
                  "spec": {
                    "summary": "Marketing managers and above at manufacturers within 20 miles of Leeds",
                    "value": {
                      "id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "dataset": "uk_contacts",
                      "dataset_version": "2026-W39",
                      "credits_per_record": 1,
                      "contacts": 12840,
                      "companies": 3115,
                      "emailable": 12310,
                      "new_to_you": null,
                      "quality": {
                        "email_coverage_pct": 96.8,
                        "verified_90d_pct": 88.4
                      },
                      "breakdowns": [
                        {
                          "by": "contact.job_level_rank",
                          "cells": [
                            {
                              "value": "director",
                              "contacts": 4120
                            }
                          ]
                        }
                      ],
                      "compliance_summary": {
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "corporate_subscriber": 12310,
                        "individual_subscriber_excluded": 530,
                        "tps_ctps_excluded": 1120,
                        "article14_notified": 12290,
                        "article14_pending_within_window": 20,
                        "suppressed_removed": [
                          {
                            "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA",
                            "removed": 260
                          }
                        ]
                      },
                      "estimate": {
                        "credits": 12310,
                        "gbp_ex_vat": {
                          "per_contact_scale": 2708.2,
                          "cheapest": 1249
                        }
                      },
                      "expires_at": "2027-09-26T10:14:00Z",
                      "engine_rules_version": "2026.09.1",
                      "defaults": [
                        {
                          "id": "active_companies",
                          "applied": true,
                          "views": [
                            "total",
                            "new_to_you",
                            "emailable"
                          ],
                          "removed": 2210
                        },
                        {
                          "id": "named_emails",
                          "applied": true,
                          "views": [
                            "emailable"
                          ],
                          "removed": 410
                        },
                        {
                          "id": "corporate_subscribers",
                          "applied": true,
                          "views": [
                            "emailable"
                          ],
                          "removed": 530
                        },
                        {
                          "id": "no_registered_phones",
                          "applied": false,
                          "views": [
                            "total",
                            "new_to_you",
                            "emailable"
                          ],
                          "removed": 1120,
                          "screened_at": "2026-09-25"
                        }
                      ],
                      "disclosure": {
                        "level": "rounded",
                        "rounded_to": 5,
                        "secondary_suppression": false,
                        "notes": [
                          "Counts under 100 and every breakdown cell are rounded to the nearest 5 for anonymous and trial callers."
                        ]
                      },
                      "premium": 8120,
                      "all_records": 12840,
                      "premium_note": "Premium at launch: in the premium export of 2026-09-28, this dataset version's as-of date."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "count_audience"
      }
    },
    "/counts/{id}": {
      "get": {
        "operationId": "getCount",
        "summary": "Get a count",
        "description": "Replay a count by id for 12 months: the effective definition, the compiled plan (expanded terms, resolved centres, SIC codes, suppression checksums), the pinned dataset and engine rules versions, all three views, breakdowns, the compliance summary, quality, the estimate and the number on the current dataset. The ETag equals the id.",
        "tags": [
          "Counts"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "counts:read"
            ]
          },
          {
            "ApiKey": [
              "counts:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "A count id from POST /v1/counts or count_audience. Either case is accepted; responses use upper case.",
            "schema": {
              "type": "string",
              "pattern": "^cnt_[A-Za-z2-7]{20}$",
              "examples": [
                "cnt_7K2PQ4MAXN3R6TBY5WDZ"
              ]
            },
            "example": "cnt_7K2PQ4MAXN3R6TBY5WDZ"
          }
        ],
        "responses": {
          "200": {
            "description": "The count as it ran.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CountReplay"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Replay of the Leeds count",
                    "value": {
                      "id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "dataset": "uk_contacts",
                      "dataset_version": "2026-W39",
                      "credits_per_record": 1,
                      "contacts": 12840,
                      "companies": 3115,
                      "emailable": 12310,
                      "new_to_you": null,
                      "quality": {
                        "email_coverage_pct": 96.8,
                        "verified_90d_pct": 88.4,
                        "verified_measured_at": "2026-09-28",
                        "deliverability": {
                          "good": 91.2,
                          "risky": 6.1,
                          "poor": 2.7
                        },
                        "avg_days_since_verification": 41
                      },
                      "breakdowns": [
                        {
                          "by": "contact.job_level_rank",
                          "cells": [
                            {
                              "value": "director",
                              "contacts": 4120
                            }
                          ]
                        }
                      ],
                      "compliance_summary": {
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "corporate_subscriber": 12310,
                        "individual_subscriber_excluded": 530,
                        "tps_ctps_excluded": 1120,
                        "article14_notified": 12290,
                        "article14_pending_within_window": 20,
                        "suppressed_removed": [
                          {
                            "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA",
                            "removed": 260
                          }
                        ]
                      },
                      "estimate": {
                        "credits": 12310,
                        "gbp_ex_vat": {
                          "per_contact_scale": 2708.2,
                          "cheapest": 1249
                        }
                      },
                      "expires_at": "2027-09-26T10:14:00Z",
                      "engine_rules_version": "2026.09.1",
                      "defaults": [
                        {
                          "id": "active_companies",
                          "applied": true,
                          "views": [
                            "total",
                            "new_to_you",
                            "emailable"
                          ],
                          "removed": 2210
                        },
                        {
                          "id": "named_emails",
                          "applied": true,
                          "views": [
                            "emailable"
                          ],
                          "removed": 410
                        },
                        {
                          "id": "corporate_subscribers",
                          "applied": true,
                          "views": [
                            "emailable"
                          ],
                          "removed": 530
                        },
                        {
                          "id": "no_registered_phones",
                          "applied": false,
                          "views": [
                            "total",
                            "new_to_you",
                            "emailable"
                          ],
                          "removed": 1120,
                          "screened_at": "2026-09-25"
                        }
                      ],
                      "disclosure": {
                        "level": "exact",
                        "rounded_to": null,
                        "secondary_suppression": false,
                        "notes": []
                      },
                      "premium": 8120,
                      "all_records": 12840,
                      "premium_note": "Premium at launch: in the premium export of 2026-09-28, this dataset version's as-of date.",
                      "as_of": "2026-09-28",
                      "level": "contact",
                      "views": {
                        "total": {
                          "contacts": 12840,
                          "companies": 3115
                        },
                        "new_to_you": null,
                        "emailable": {
                          "contacts": 12310,
                          "companies": 3002
                        },
                        "premium": {
                          "contacts": 8120,
                          "companies": 2240
                        },
                        "all_records": {
                          "contacts": 12840,
                          "companies": 3115
                        }
                      },
                      "expanded_terms": [
                        {
                          "term": "Marketing Manager",
                          "from_term": "marketing manager",
                          "expansion_set": "input",
                          "contacts": 6210
                        },
                        {
                          "term": "Marketing Managers",
                          "from_term": "marketing manager",
                          "expansion_set": "plural_singular",
                          "contacts": 14
                        },
                        {
                          "term": "Mktg Manager",
                          "from_term": "marketing manager",
                          "expansion_set": "abbreviations",
                          "contacts": "under 10"
                        }
                      ],
                      "effective_audience": {
                        "schema": "mydatahub.audience/1",
                        "dataset": "uk_contacts",
                        "dataset_version": "2026-W39",
                        "where": {
                          "all": [
                            {
                              "field": "site.location",
                              "op": "within_radius",
                              "centre": {
                                "place": "Leeds"
                              },
                              "radius_miles": 20
                            },
                            {
                              "field": "contact.title",
                              "op": "matches",
                              "terms": [
                                "marketing manager"
                              ],
                              "mode": "contains",
                              "expand": [
                                "plural_singular",
                                "department_synonyms",
                                "ampersand_and",
                                "abbreviations"
                              ]
                            },
                            {
                              "field": "company.employee_band",
                              "op": "gte",
                              "value": "50-99"
                            },
                            {
                              "field": "company.sic_2007",
                              "op": "in",
                              "values": [
                                "C"
                              ]
                            },
                            {
                              "field": "company.status",
                              "op": "in",
                              "values": [
                                "active"
                              ]
                            },
                            {
                              "field": "contact.job_level_rank",
                              "op": "in",
                              "values": [
                                1,
                                2,
                                3,
                                4,
                                5,
                                6,
                                8,
                                9
                              ]
                            },
                            {
                              "not": {
                                "field": "email.address_sha256",
                                "op": "in_list",
                                "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                              }
                            }
                          ]
                        },
                        "email_policy": {
                          "min_deliverability_score": 70,
                          "allow_catch_all": false
                        },
                        "dedupe": "none"
                      },
                      "plan": {
                        "engine_rules_version": "2026.09.1",
                        "defaults_applied": [
                          "active_companies",
                          "named_emails",
                          "corporate_subscribers"
                        ],
                        "expanded_terms": [
                          {
                            "term": "Marketing Manager",
                            "from_term": "marketing manager",
                            "expansion_set": "input",
                            "contacts": 6210
                          },
                          {
                            "term": "Marketing Managers",
                            "from_term": "marketing manager",
                            "expansion_set": "plural_singular",
                            "contacts": 14
                          },
                          {
                            "term": "Mktg Manager",
                            "from_term": "marketing manager",
                            "expansion_set": "abbreviations",
                            "contacts": "under 10"
                          }
                        ],
                        "centres": [
                          {
                            "label": "Leeds",
                            "code": "E08000035",
                            "lat": 53.7997,
                            "lon": -1.5492,
                            "radius_miles": 20,
                            "postcode_districts_matched": 64
                          }
                        ],
                        "sic_codes": [],
                        "geography_sets": [],
                        "suppressions": [
                          {
                            "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA",
                            "checksum": "9f2c4e0a1b7d3c5e8f6a2b4c6d8e0f1a3b5c7d9e1f2a4b6c8d0e2f4a6b8c0d2e",
                            "row_count": 1198
                          }
                        ]
                      },
                      "current": {
                        "dataset_version": "2026-W40",
                        "contacts": 12861,
                        "companies": 3119
                      },
                      "removed_since": 3,
                      "created_at": "2026-09-26T10:14:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/previews": {
      "post": {
        "operationId": "createPreview",
        "summary": "Preview sample records",
        "description": "Up to 25 masked sample rows from a seed fixed per audience, so a repeat returns the same rows. Each row has verification badges, why it matches and a provenance card with the compliance object. No rows when the count is under 25. Free.",
        "tags": [
          "Counts"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "previews:read"
            ]
          },
          {
            "ApiKey": [
              "previews:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Ten rows of the Leeds count",
                  "value": {
                    "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                    "limit": 10
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The sample.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preview"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Ten rows of the Leeds count",
                    "value": {
                      "id": "prv_01JB4H3M7Q2V7XN3M9R6T1Y5W8",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "dataset_version": "2026-W39",
                      "seed": "7k2pq4ma",
                      "count": 12840,
                      "rows": [
                        {
                          "id": "prv_01JB4H3N2V7XN3M9R6T1Y5W8ZA",
                          "title": "Marketing Director",
                          "job_level": "Director",
                          "job_function": "Marketing",
                          "company": {
                            "name": "Example Manufacturing Ltd",
                            "companies_house_number": "12345678",
                            "status": "active",
                            "employee_band": "100-199",
                            "sic_2007": [
                              "C"
                            ]
                          },
                          "site": {
                            "town": "Leeds",
                            "postcode_district": "LS11",
                            "region": "yorkshire_and_the_humber"
                          },
                          "email_masked": "j••••@••••.co.uk",
                          "email_type": "named",
                          "phone_masked": "0113 ••• •••1",
                          "tps_ctps_status": "clear",
                          "badges": [
                            {
                              "badge": "verified",
                              "date": "2026-09-10",
                              "label": "Verified 10 September 2026"
                            }
                          ],
                          "why_it_matches": [
                            {
                              "pointer": "/where/all/0",
                              "field": "contact.title",
                              "value": "Marketing Director",
                              "explanation": "Marketing Director matched marketing manager through expansion."
                            },
                            {
                              "pointer": "/where/all/3",
                              "field": "company.employee_band",
                              "value": "100-199",
                              "explanation": "Employees 120, inside 50 or more."
                            }
                          ],
                          "provenance": {
                            "sources": {
                              "title": "emailmovers_research",
                              "company": "companies_house",
                              "email": "emailmovers_research"
                            },
                            "first_seen_at": "2026-05-02",
                            "last_verified_at": "2026-08-30",
                            "method": "telephone",
                            "companies_house_number": "12345678",
                            "company_status": "active",
                            "article14_status": "notified",
                            "tps_ctps_screened_at": "2026-09-12",
                            "lawful_basis": "legitimate_interests_art6_1_f"
                          },
                          "compliance": {
                            "lawful_basis": "legitimate_interests_art6_1_f",
                            "lia_ref": "EM-LIA-2026-03",
                            "subscriber_class": "ltd",
                            "corporate_subscriber": true,
                            "email_marketing_basis": "pecr_corporate_subscriber",
                            "subscriber_evidence": {
                              "companies_house_number": "12345678",
                              "company_type": "ltd"
                            },
                            "article14_status": "notified",
                            "article14_notified_at": "2026-06-14",
                            "notice_version": "2026-02",
                            "provenance": {
                              "company": {
                                "source": "companies_house",
                                "as_of": "2026-09-21"
                              },
                              "contact": {
                                "source": "emailmovers_research",
                                "compiled_at": "2026-05-02",
                                "last_verified_at": "2026-08-30",
                                "method": "telephone"
                              },
                              "email": {
                                "verified_at": "2026-09-10",
                                "result": "ok",
                                "provider_location": "EU"
                              }
                            },
                            "tps_ctps_status": "clear",
                            "tps_ctps_screened_at": "2026-09-12",
                            "tps_ctps_valid_until": "2026-10-10",
                            "suppression_status": "none",
                            "record_age_days": 147,
                            "attribution": "Contains public sector information licensed under the Open Government Licence v3.0"
                          }
                        }
                      ],
                      "withheld": null,
                      "masked": true,
                      "watermark": null,
                      "created_at": "2026-09-26T10:15:00Z",
                      "disclosure": {
                        "level": "rounded",
                        "rounded_to": 5,
                        "secondary_suppression": false,
                        "notes": [
                          "Counts under 100 and every breakdown cell are rounded to the nearest 5 for anonymous and trial callers."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "preview_records"
      }
    },
    "/sample-requests": {
      "post": {
        "operationId": "createSampleRequest",
        "summary": "Ask for a sample of a count",
        "description": "Starts a sample of about 10 records of a counted audience: the person then confirms a work email address and downloads it once. The count must allow a sample under the caller's rules (25 records or more, not one company). Never returns records.",
        "tags": [
          "Samples"
        ],
        "security": [
          {
            "OAuth2": [
              "samples:request"
            ]
          },
          {
            "ApiKey": [
              "samples:request"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SampleRequestCreate"
              },
              "examples": {
                "illustrative": {
                  "summary": "A sample of the Leeds count",
                  "value": {
                    "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The request, waiting for the address.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SampleRequest"
                },
                "examples": {
                  "illustrative": {
                    "summary": "A sample of the Leeds count",
                    "value": {
                      "id": "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "status": "awaiting_email",
                      "created_at": "2026-10-11T10:00:00Z",
                      "expires_at": "2026-10-12T10:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/sample-requests/{id}/email": {
      "post": {
        "operationId": "createSampleRequestEmail",
        "summary": "Send the confirmation link for a sample",
        "description": "The person's work email address, from the calling server's own form, never through a model. A one-time link is emailed; the answer is the same whether the address was accepted or refused (suppressed, objecting, over a limit), so it cannot be used to test addresses. Free webmail and malformed addresses get 422.",
        "tags": [
          "Samples"
        ],
        "security": [
          {
            "OAuth2": [
              "samples:request"
            ]
          },
          {
            "ApiKey": [
              "samples:request"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a sample request id: smr_ followed by a 26 character ULID in upper case Crockford base32, such as smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6.",
            "schema": {
              "type": "string",
              "pattern": "^smr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6"
              ]
            },
            "example": "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SampleRequestEmail"
              },
              "examples": {
                "illustrative": {
                  "summary": "The address from the form",
                  "value": {
                    "email": "jordan.hale@example.co.uk",
                    "follow_up": false,
                    "wording": "2026-10-11"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Taken: the person checks their inbox.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SampleRequestEmailAccepted"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The address from the form",
                    "value": {
                      "status": "check_your_inbox"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/sample-requests/{id}": {
      "get": {
        "operationId": "getSampleRequest",
        "summary": "Get a sample request",
        "description": "The request's status only: never the address or the records.",
        "tags": [
          "Samples"
        ],
        "security": [
          {
            "OAuth2": [
              "samples:request"
            ]
          },
          {
            "ApiKey": [
              "samples:request"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a sample request id: smr_ followed by a 26 character ULID in upper case Crockford base32, such as smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6.",
            "schema": {
              "type": "string",
              "pattern": "^smr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6"
              ]
            },
            "example": "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6"
          }
        ],
        "responses": {
          "200": {
            "description": "The request.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SampleRequest"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Waiting for the person to confirm",
                    "value": {
                      "id": "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "status": "email_sent",
                      "created_at": "2026-10-11T10:00:00Z",
                      "expires_at": "2026-10-12T10:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/sample-downloads": {
      "post": {
        "operationId": "createSampleDownload",
        "summary": "Confirm a sample and get its download link",
        "description": "Sent by the confirmation page when the person presses its button, with the token from the emailed link; the token is the credential, so no key or session is needed. The first press confirms the address and chooses up to 10 records (verified named emails with an Article 14 notice, none at the person's own domain, at most 2 a company), read afresh against every suppression. Each press until the download gives a new single-use link for 5 minutes; after it, the answer says the sample was already downloaded. An unknown or expired token gets 404.",
        "tags": [
          "Samples"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SampleDownloadCreate"
              },
              "examples": {
                "illustrative": {
                  "summary": "The person presses Download your sample",
                  "value": {
                    "token": "q3V8xN2fK7mR1tY6pL0sD4hJ9wZ5cB8eA2gU7iO3nQ1"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The sample's link, or why there is none.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SampleDownload"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The person presses Download your sample",
                    "value": {
                      "status": "ready",
                      "records": 10,
                      "download_url": "/files/samples/sdl_Xr4mP8qT2vN6kJ1wL9sF3hD7bG5cZ0yA8eU2iO6nQ4t",
                      "expires_at": "2026-10-11T10:20:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/audiences": {
      "get": {
        "operationId": "listAudiences",
        "summary": "List saved audiences",
        "description": "Saved audiences shared across the organisation, with current counts and last refresh.",
        "tags": [
          "Audiences"
        ],
        "security": [
          {
            "OAuth2": [
              "audiences:read"
            ]
          },
          {
            "ApiKey": [
              "audiences:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Filter by name.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of saved audiences.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedAudienceList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "One saved audience",
                    "value": {
                      "data": [
                        {
                          "id": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA",
                          "name": "Marketing directors, Leeds",
                          "audience": {
                            "schema": "mydatahub.audience/1",
                            "dataset": "uk_contacts",
                            "dataset_version": "2026-W39",
                            "where": {
                              "all": [
                                {
                                  "field": "contact.title",
                                  "op": "matches",
                                  "terms": [
                                    "marketing manager"
                                  ],
                                  "mode": "contains",
                                  "expand": [
                                    "plural_singular",
                                    "department_synonyms",
                                    "ampersand_and",
                                    "abbreviations"
                                  ]
                                },
                                {
                                  "field": "contact.job_level_rank",
                                  "op": "in",
                                  "values": [
                                    1,
                                    2,
                                    3,
                                    4,
                                    5,
                                    6,
                                    8,
                                    9
                                  ]
                                },
                                {
                                  "field": "company.sic_2007",
                                  "op": "in",
                                  "values": [
                                    "C"
                                  ]
                                },
                                {
                                  "field": "company.employee_band",
                                  "op": "gte",
                                  "value": "50-99"
                                },
                                {
                                  "field": "site.location",
                                  "op": "within_radius",
                                  "centre": {
                                    "place": "Leeds"
                                  },
                                  "radius_miles": 20
                                },
                                {
                                  "not": {
                                    "field": "email.address_sha256",
                                    "op": "in_list",
                                    "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                                  }
                                }
                              ]
                            },
                            "email_policy": {
                              "min_deliverability_score": 70,
                              "allow_catch_all": false
                            },
                            "dedupe": "none"
                          },
                          "brief": "Marketing managers and above at manufacturers within 20 miles of Leeds",
                          "current_count": {
                            "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                            "dataset_version": "2026-W39",
                            "contacts": 12840,
                            "companies": 3115,
                            "emailable": 12310,
                            "counted_at": "2026-09-26T10:14:00Z"
                          },
                          "last_refreshed_at": "2026-09-28T06:00:00Z",
                          "created_at": "2026-09-26T10:20:00Z",
                          "updated_at": "2026-09-26T10:20:00Z",
                          "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                          "url": "https://mydatahub.emailmovers.com/audiences/aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "list_audiences"
      },
      "post": {
        "operationId": "createAudience",
        "summary": "Save an audience",
        "description": "Save a named audience definition, shared across the organisation. Saving is free; it is counted at once and on every refresh.",
        "tags": [
          "Audiences"
        ],
        "security": [
          {
            "OAuth2": [
              "audiences:write"
            ]
          },
          {
            "ApiKey": [
              "audiences:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavedAudienceRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Save the Leeds audience",
                  "value": {
                    "name": "Marketing directors, Leeds",
                    "audience": {
                      "schema": "mydatahub.audience/1",
                      "dataset": "uk_contacts",
                      "dataset_version": "2026-W39",
                      "where": {
                        "all": [
                          {
                            "field": "contact.title",
                            "op": "matches",
                            "terms": [
                              "marketing manager"
                            ],
                            "mode": "contains",
                            "expand": [
                              "plural_singular",
                              "department_synonyms",
                              "ampersand_and",
                              "abbreviations"
                            ]
                          },
                          {
                            "field": "contact.job_level_rank",
                            "op": "in",
                            "values": [
                              1,
                              2,
                              3,
                              4,
                              5,
                              6,
                              8,
                              9
                            ]
                          },
                          {
                            "field": "company.sic_2007",
                            "op": "in",
                            "values": [
                              "C"
                            ]
                          },
                          {
                            "field": "company.employee_band",
                            "op": "gte",
                            "value": "50-99"
                          },
                          {
                            "field": "site.location",
                            "op": "within_radius",
                            "centre": {
                              "place": "Leeds"
                            },
                            "radius_miles": 20
                          },
                          {
                            "not": {
                              "field": "email.address_sha256",
                              "op": "in_list",
                              "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                            }
                          }
                        ]
                      },
                      "email_policy": {
                        "min_deliverability_score": 70,
                        "allow_catch_all": false
                      },
                      "dedupe": "none"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The saved audience.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedAudience"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Save the Leeds audience",
                    "value": {
                      "id": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA",
                      "name": "Marketing directors, Leeds",
                      "audience": {
                        "schema": "mydatahub.audience/1",
                        "dataset": "uk_contacts",
                        "dataset_version": "2026-W39",
                        "where": {
                          "all": [
                            {
                              "field": "contact.title",
                              "op": "matches",
                              "terms": [
                                "marketing manager"
                              ],
                              "mode": "contains",
                              "expand": [
                                "plural_singular",
                                "department_synonyms",
                                "ampersand_and",
                                "abbreviations"
                              ]
                            },
                            {
                              "field": "contact.job_level_rank",
                              "op": "in",
                              "values": [
                                1,
                                2,
                                3,
                                4,
                                5,
                                6,
                                8,
                                9
                              ]
                            },
                            {
                              "field": "company.sic_2007",
                              "op": "in",
                              "values": [
                                "C"
                              ]
                            },
                            {
                              "field": "company.employee_band",
                              "op": "gte",
                              "value": "50-99"
                            },
                            {
                              "field": "site.location",
                              "op": "within_radius",
                              "centre": {
                                "place": "Leeds"
                              },
                              "radius_miles": 20
                            },
                            {
                              "not": {
                                "field": "email.address_sha256",
                                "op": "in_list",
                                "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                              }
                            }
                          ]
                        },
                        "email_policy": {
                          "min_deliverability_score": 70,
                          "allow_catch_all": false
                        },
                        "dedupe": "none"
                      },
                      "brief": "Marketing managers and above at manufacturers within 20 miles of Leeds",
                      "current_count": {
                        "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                        "dataset_version": "2026-W39",
                        "contacts": 12840,
                        "companies": 3115,
                        "emailable": 12310,
                        "counted_at": "2026-09-26T10:14:00Z"
                      },
                      "last_refreshed_at": "2026-09-28T06:00:00Z",
                      "created_at": "2026-09-26T10:20:00Z",
                      "updated_at": "2026-09-26T10:20:00Z",
                      "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                      "url": "https://mydatahub.emailmovers.com/audiences/aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional",
        "x-mcp-tool": "save_audience"
      }
    },
    "/audiences/{id}": {
      "get": {
        "operationId": "getAudience",
        "summary": "Get a saved audience",
        "description": "One saved audience with its definition and current count.",
        "tags": [
          "Audiences"
        ],
        "security": [
          {
            "OAuth2": [
              "audiences:read"
            ]
          },
          {
            "ApiKey": [
              "audiences:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
          }
        ],
        "responses": {
          "200": {
            "description": "The saved audience.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedAudience"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The Leeds audience",
                    "value": {
                      "id": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA",
                      "name": "Marketing directors, Leeds",
                      "audience": {
                        "schema": "mydatahub.audience/1",
                        "dataset": "uk_contacts",
                        "dataset_version": "2026-W39",
                        "where": {
                          "all": [
                            {
                              "field": "contact.title",
                              "op": "matches",
                              "terms": [
                                "marketing manager"
                              ],
                              "mode": "contains",
                              "expand": [
                                "plural_singular",
                                "department_synonyms",
                                "ampersand_and",
                                "abbreviations"
                              ]
                            },
                            {
                              "field": "contact.job_level_rank",
                              "op": "in",
                              "values": [
                                1,
                                2,
                                3,
                                4,
                                5,
                                6,
                                8,
                                9
                              ]
                            },
                            {
                              "field": "company.sic_2007",
                              "op": "in",
                              "values": [
                                "C"
                              ]
                            },
                            {
                              "field": "company.employee_band",
                              "op": "gte",
                              "value": "50-99"
                            },
                            {
                              "field": "site.location",
                              "op": "within_radius",
                              "centre": {
                                "place": "Leeds"
                              },
                              "radius_miles": 20
                            },
                            {
                              "not": {
                                "field": "email.address_sha256",
                                "op": "in_list",
                                "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                              }
                            }
                          ]
                        },
                        "email_policy": {
                          "min_deliverability_score": 70,
                          "allow_catch_all": false
                        },
                        "dedupe": "none"
                      },
                      "brief": "Marketing managers and above at manufacturers within 20 miles of Leeds",
                      "current_count": {
                        "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                        "dataset_version": "2026-W39",
                        "contacts": 12840,
                        "companies": 3115,
                        "emailable": 12310,
                        "counted_at": "2026-09-26T10:14:00Z"
                      },
                      "last_refreshed_at": "2026-09-28T06:00:00Z",
                      "created_at": "2026-09-26T10:20:00Z",
                      "updated_at": "2026-09-26T10:20:00Z",
                      "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                      "url": "https://mydatahub.emailmovers.com/audiences/aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      },
      "patch": {
        "operationId": "updateAudience",
        "summary": "Update a saved audience",
        "description": "Rename a saved audience or replace its definition. The next count uses the new definition.",
        "tags": [
          "Audiences"
        ],
        "security": [
          {
            "OAuth2": [
              "audiences:write"
            ]
          },
          {
            "ApiKey": [
              "audiences:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavedAudienceUpdate"
              },
              "examples": {
                "illustrative": {
                  "summary": "Rename the Leeds audience",
                  "value": {
                    "name": "Marketing directors, Leeds"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated audience.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedAudience"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Rename the Leeds audience",
                    "value": {
                      "id": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA",
                      "name": "Marketing directors, Leeds",
                      "audience": {
                        "schema": "mydatahub.audience/1",
                        "dataset": "uk_contacts",
                        "dataset_version": "2026-W39",
                        "where": {
                          "all": [
                            {
                              "field": "contact.title",
                              "op": "matches",
                              "terms": [
                                "marketing manager"
                              ],
                              "mode": "contains",
                              "expand": [
                                "plural_singular",
                                "department_synonyms",
                                "ampersand_and",
                                "abbreviations"
                              ]
                            },
                            {
                              "field": "contact.job_level_rank",
                              "op": "in",
                              "values": [
                                1,
                                2,
                                3,
                                4,
                                5,
                                6,
                                8,
                                9
                              ]
                            },
                            {
                              "field": "company.sic_2007",
                              "op": "in",
                              "values": [
                                "C"
                              ]
                            },
                            {
                              "field": "company.employee_band",
                              "op": "gte",
                              "value": "50-99"
                            },
                            {
                              "field": "site.location",
                              "op": "within_radius",
                              "centre": {
                                "place": "Leeds"
                              },
                              "radius_miles": 20
                            },
                            {
                              "not": {
                                "field": "email.address_sha256",
                                "op": "in_list",
                                "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                              }
                            }
                          ]
                        },
                        "email_policy": {
                          "min_deliverability_score": 70,
                          "allow_catch_all": false
                        },
                        "dedupe": "none"
                      },
                      "brief": "Marketing managers and above at manufacturers within 20 miles of Leeds",
                      "current_count": {
                        "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                        "dataset_version": "2026-W39",
                        "contacts": 12840,
                        "companies": 3115,
                        "emailable": 12310,
                        "counted_at": "2026-09-26T10:14:00Z"
                      },
                      "last_refreshed_at": "2026-09-28T06:00:00Z",
                      "created_at": "2026-09-26T10:20:00Z",
                      "updated_at": "2026-09-26T10:20:00Z",
                      "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                      "url": "https://mydatahub.emailmovers.com/audiences/aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "save_audience"
      },
      "delete": {
        "operationId": "deleteAudience",
        "summary": "Delete a saved audience",
        "description": "Delete a saved audience. Counts, quotes and orders made from it keep their own ids and still replay.",
        "tags": [
          "Audiences"
        ],
        "security": [
          {
            "OAuth2": [
              "audiences:write"
            ]
          },
          {
            "ApiKey": [
              "audiences:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/audiences/{id}/refresh": {
      "post": {
        "operationId": "refreshAudience",
        "summary": "Refresh a saved audience",
        "description": "Recount a saved audience on the current dataset version and return the difference. The audience.refreshed webhook carries the same object. Free.",
        "tags": [
          "Audiences"
        ],
        "security": [
          {
            "OAuth2": [
              "audiences:write"
            ]
          },
          {
            "ApiKey": [
              "audiences:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
          }
        ],
        "responses": {
          "200": {
            "description": "The refresh and its diff.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceRefresh"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Refresh the Leeds audience",
                    "value": {
                      "audience_id": "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA",
                      "previous": {
                        "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                        "dataset_version": "2026-W39",
                        "contacts": 12840,
                        "companies": 3115,
                        "emailable": 12310,
                        "counted_at": "2026-09-26T10:14:00Z"
                      },
                      "current": {
                        "count_id": "cnt_Q3N5X2M7K4P6R2T4V4W6",
                        "dataset_version": "2026-W40",
                        "contacts": 13054,
                        "companies": 3160,
                        "emailable": 12520,
                        "counted_at": "2026-10-05T06:00:00Z"
                      },
                      "diff": {
                        "contacts": 214,
                        "companies": 45,
                        "emailable": 210,
                        "new_records": 231,
                        "removed_records": 17
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/quotes": {
      "post": {
        "operationId": "createQuote",
        "summary": "Quote an order",
        "description": "A signed machine quote for a count, field set, quantity and licence: records after overlap and suppression, credits per record, credits, the GBP price, the balance after, the licence and warranty, and blockers. Valid 24 hours and bound to a dataset version and the caller's organisation. Free, and needs no account. This is not a human sales quote, which is a 14 day PDF made in the app.",
        "tags": [
          "Quotes"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "quotes:read"
            ]
          },
          {
            "ApiKey": [
              "quotes:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              },
              "examples": {
                "spec": {
                  "summary": "5,000 of the Leeds records on the standard field set",
                  "value": {
                    "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                    "field_set": "standard",
                    "limit": 5000,
                    "dedupe_against": "previous_orders",
                    "licence": "multi_use_12m"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The machine quote.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MachineQuote"
                },
                "examples": {
                  "spec": {
                    "summary": "5,000 of the Leeds records on the standard field set",
                    "value": {
                      "id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                      "kind": "machine",
                      "dataset_version": "2026-W39",
                      "records": 5000,
                      "removed": {
                        "already_held": 312,
                        "suppressed": 41
                      },
                      "credits_required": 5000,
                      "credits_available": 6200,
                      "gbp_ex_vat": 1249,
                      "licence": {
                        "type": "multi_use_12m",
                        "reuse_until": "2027-09-26",
                        "resale_prohibited": true,
                        "permitted_channels": [
                          "email",
                          "telephone",
                          "post"
                        ],
                        "warranty_url": "https://emailmovers.com/trust/warranty",
                        "terms_version": "2026-09"
                      },
                      "warranty": {
                        "policy": "replace_over_threshold_hard_bounce",
                        "threshold_percent": 10,
                        "url": "https://emailmovers.com/trust/warranty"
                      },
                      "expires_at": "2026-09-27T10:14:00Z",
                      "blockers": [],
                      "organisation_id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "credits_per_record": 1,
                      "balance_after": 1200,
                      "purchase": {
                        "credits_to_buy": 0,
                        "cheapest": null,
                        "gbp_ex_vat": 0,
                        "options": []
                      },
                      "signature": {
                        "alg": "ES256",
                        "kid": "qte-2026-09",
                        "jwks_url": "https://mydatahub.emailmovers.com/.well-known/jwks.json",
                        "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6InF0ZS0yMDI2LTA5In0.eyJpZCI6InF0ZV8wMUpCNE0yUjZUMVk1VzhaQUs4UTJWN1hOMyJ9.MEUCIQDexampleSignatureOnly"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-idempotency-key": "optional",
        "x-mcp-tool": "quote_order"
      }
    },
    "/quotes/{id}": {
      "get": {
        "operationId": "getQuote",
        "summary": "Get a quote",
        "description": "A machine quote (kind machine, 24 hours) or a human sales quote (kind sales, 14 days). An agent in the same organisation can settle another agent's machine quote after checking its signature, dataset version and expiry; outside the organisation, re-quote.",
        "tags": [
          "Quotes"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "quotes:read"
            ]
          },
          {
            "ApiKey": [
              "quotes:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a quote id: qte_ followed by a 26 character ULID in upper case Crockford base32, such as qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3.",
            "schema": {
              "type": "string",
              "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
              ]
            },
            "example": "qte_01JB4P2V7XN3M9R6T1Y5W8ZAK8"
          }
        ],
        "responses": {
          "200": {
            "description": "The quote.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                },
                "examples": {
                  "illustrative": {
                    "summary": "A human sales quote",
                    "value": {
                      "id": "qte_01JB4P2V7XN3M9R6T1Y5W8ZAK8",
                      "kind": "sales",
                      "status": "sent",
                      "created_at": "2026-09-26T11:00:00Z",
                      "valid_until": "2026-10-10",
                      "created_by": {
                        "role": "account_manager",
                        "name": "Jordan Hale"
                      },
                      "customer": "Example Agency Ltd",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "field_set": "standard",
                      "records": 12310,
                      "credits_per_record": 1,
                      "lines": [
                        {
                          "description": "12,310 UK records, standard field set, 12-month multi-use licence",
                          "quantity": 12310,
                          "unit_price_gbp": 0.22,
                          "amount_gbp": 2708.2
                        }
                      ],
                      "subtotal_gbp_ex_vat": 2708.2,
                      "vat_gbp": 541.64,
                      "total_gbp_inc_vat": 3249.84,
                      "balance_after": 6200,
                      "licence": {
                        "type": "multi_use_12m",
                        "reuse_until": "2027-09-26",
                        "resale_prohibited": true,
                        "permitted_channels": [
                          "email",
                          "telephone",
                          "post"
                        ],
                        "warranty_url": "https://emailmovers.com/trust/warranty",
                        "terms_version": "2026-09"
                      },
                      "warranty": {
                        "policy": "replace_over_threshold_hard_bounce",
                        "threshold_percent": 10,
                        "url": "https://emailmovers.com/trust/warranty"
                      },
                      "payment_methods": [
                        "card",
                        "invoice"
                      ],
                      "pay_url": "https://mydatahub.emailmovers.com/quotes/qte_01JB4P2V7XN3M9R6T1Y5W8ZAK8/pay",
                      "pdf_url": "https://mydatahub.emailmovers.com/quotes/qte_01JB4P2V7XN3M9R6T1Y5W8ZAK8.pdf"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/orders": {
      "post": {
        "operationId": "createOrder",
        "summary": "Create an order (spends credits)",
        "description": "Spend credits against a live machine quote: 1 credit per complete UK record. Needs the quote_id plus a human confirmation (MCP elicitation, the confirmation_token from the approval page, or a person ordering in the app itself) or a pre-authorised agent key within its per-order cap and monthly budget; a model-set confirmed flag is never consent. A standard API key or an OAuth token with no confirmation gets 403 confirmation-required carrying the approval_url, and nothing is charged. Idempotent on quote_id plus the Idempotency-Key header, so a retry never double charges. Returns 402 with the machine quote and a top_up_url when the balance is short, 403 agent-budget-exceeded when a key's limits do not cover it, 403 business-details-required when an account made by self-serve sign-up has not yet confirmed its business name and that it is a UK business (PATCH /v1/account), and 403 licence-acceptance-required, with the approval_url, when the Data Licence and Sharing Agreement in force was not accepted (licence_accepted_version from a person in the app, the approval page's token, or the agent key's own acceptance). Lawful basis for named work emails is UK GDPR Article 6(1)(f) legitimate interests; sole traders and ordinary partnerships are individual subscribers and are left out of email audiences by default.",
        "tags": [
          "Orders"
        ],
        "security": [
          {
            "OAuth2": [
              "orders:write"
            ]
          },
          {
            "ApiKey": [
              "orders:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyRequired"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderRequest"
              },
              "examples": {
                "spec": {
                  "summary": "Order the quoted 5,000 records",
                  "value": {
                    "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                    "name": "Leeds marketing Q4",
                    "delivery": [
                      "api",
                      "csv"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The order, queued.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "spec": {
                    "summary": "Order the quoted 5,000 records",
                    "value": {
                      "id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "status": "queued",
                      "credits_charged": 5000,
                      "records": 5000,
                      "confirmed_by": {
                        "method": "agent_key",
                        "key_id": "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA",
                        "client_id": "https://claude.ai/oauth/claude-code-client-metadata"
                      },
                      "records_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/records",
                      "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "credits_remaining": 1200,
                      "cost_gbp": 1495,
                      "licence_expires_at": "2027-09-26",
                      "licence": {
                        "type": "multi_use_12m",
                        "reuse_until": "2027-09-26",
                        "resale_prohibited": true,
                        "permitted_channels": [
                          "email",
                          "telephone",
                          "post"
                        ],
                        "warranty_url": "https://emailmovers.com/trust/warranty",
                        "terms_version": "2026-09"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 1,
        "x-cost-unit": "record",
        "x-cost-note": "1 credit per complete UK record (uk_contacts). Suppressed, duplicate and already held records cost 0.",
        "x-free": false,
        "x-anonymous": false,
        "x-idempotency-key": "required",
        "x-mcp-tool": "create_order"
      },
      "get": {
        "operationId": "listOrders",
        "summary": "List orders",
        "description": "Recent orders with status, counts and links, newest first.",
        "tags": [
          "Orders"
        ],
        "security": [
          {
            "OAuth2": [
              "orders:read"
            ]
          },
          {
            "ApiKey": [
              "orders:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "queued, building, verifying, ready; failed if processing failed; cancelled (only while queued).",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "building",
                "verifying",
                "ready",
                "failed",
                "cancelled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of orders.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Recent orders",
                    "value": {
                      "data": [
                        {
                          "id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                          "status": "ready",
                          "credits_charged": 5000,
                          "records": 5000,
                          "confirmed_by": {
                            "method": "agent_key",
                            "key_id": "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA",
                            "client_id": "https://claude.ai/oauth/claude-code-client-metadata",
                            "user_agent": "claude-code/2.1",
                            "mtls_certificate_fingerprint": null,
                            "web_bot_auth_signature_agent": null,
                            "confirmed_at": "2026-09-26T10:16:00Z"
                          },
                          "records_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/records",
                          "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                          "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                          "credits_remaining": 1200,
                          "cost_gbp": 1495,
                          "licence_expires_at": "2027-09-26",
                          "licence": {
                            "type": "multi_use_12m",
                            "reuse_until": "2027-09-26",
                            "resale_prohibited": true,
                            "permitted_channels": [
                              "email",
                              "telephone",
                              "post"
                            ],
                            "warranty_url": "https://emailmovers.com/trust/warranty",
                            "terms_version": "2026-09"
                          },
                          "name": "Leeds marketing Q4",
                          "dataset_version": "2026-W39",
                          "field_set": "standard",
                          "delivery": [
                            "api",
                            "csv"
                          ],
                          "verification": {
                            "checked": 5000,
                            "passed": 4962,
                            "replaced": 38
                          },
                          "download_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/download",
                          "receipt_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/receipt",
                          "validation_report": {
                            "pdf_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/validation-report.pdf",
                            "json_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/validation-report.json"
                          },
                          "buyer_kit": {
                            "draft_lia_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/lia",
                            "first_email_wording_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/first-email",
                            "article30_stub_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/article30",
                            "due_diligence_file_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/due-diligence"
                          },
                          "created_at": "2026-09-26T10:16:00Z",
                          "ready_at": "2026-09-26T10:16:04Z",
                          "failure": null
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "get_order"
      }
    },
    "/orders/{id}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Get an order",
        "description": "Status (queued, building, verifying, ready, failed, cancelled), counts, charges, the licence, the buyer kit and the links to records, download and receipt.",
        "tags": [
          "Orders"
        ],
        "security": [
          {
            "OAuth2": [
              "orders:read"
            ]
          },
          {
            "ApiKey": [
              "orders:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "schema": {
              "type": "string",
              "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
              ]
            },
            "example": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "illustrative": {
                    "summary": "A ready order",
                    "value": {
                      "id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "status": "ready",
                      "credits_charged": 5000,
                      "records": 5000,
                      "confirmed_by": {
                        "method": "agent_key",
                        "key_id": "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA",
                        "client_id": "https://claude.ai/oauth/claude-code-client-metadata",
                        "user_agent": "claude-code/2.1",
                        "mtls_certificate_fingerprint": null,
                        "web_bot_auth_signature_agent": null,
                        "confirmed_at": "2026-09-26T10:16:00Z"
                      },
                      "records_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/records",
                      "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "credits_remaining": 1200,
                      "cost_gbp": 1495,
                      "licence_expires_at": "2027-09-26",
                      "licence": {
                        "type": "multi_use_12m",
                        "reuse_until": "2027-09-26",
                        "resale_prohibited": true,
                        "permitted_channels": [
                          "email",
                          "telephone",
                          "post"
                        ],
                        "warranty_url": "https://emailmovers.com/trust/warranty",
                        "terms_version": "2026-09"
                      },
                      "name": "Leeds marketing Q4",
                      "dataset_version": "2026-W39",
                      "field_set": "standard",
                      "delivery": [
                        "api",
                        "csv"
                      ],
                      "verification": {
                        "checked": 5000,
                        "passed": 4962,
                        "replaced": 38
                      },
                      "download_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/download",
                      "receipt_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/receipt",
                      "validation_report": {
                        "pdf_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/validation-report.pdf",
                        "json_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/validation-report.json"
                      },
                      "buyer_kit": {
                        "draft_lia_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/lia",
                        "first_email_wording_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/first-email",
                        "article30_stub_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/article30",
                        "due_diligence_file_url": "https://mydatahub.emailmovers.com/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/kit/due-diligence"
                      },
                      "created_at": "2026-09-26T10:16:00Z",
                      "ready_at": "2026-09-26T10:16:04Z",
                      "failure": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "get_order"
      }
    },
    "/orders/{id}/cancel": {
      "post": {
        "operationId": "cancelOrder",
        "summary": "Cancel a queued order",
        "description": "Cancel an order while it is queued; its credits are refunded in full. Later statuses return 409.",
        "tags": [
          "Orders"
        ],
        "security": [
          {
            "OAuth2": [
              "orders:write"
            ]
          },
          {
            "ApiKey": [
              "orders:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "schema": {
              "type": "string",
              "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
              ]
            },
            "example": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
          }
        ],
        "responses": {
          "200": {
            "description": "The cancelled order.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Cancel a queued order",
                    "value": {
                      "id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "status": "cancelled",
                      "credits_charged": 0,
                      "records": 5000,
                      "confirmed_by": {
                        "method": "agent_key",
                        "key_id": "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA",
                        "client_id": "https://claude.ai/oauth/claude-code-client-metadata"
                      },
                      "records_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/records",
                      "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "credits_remaining": 6200,
                      "cost_gbp": 0,
                      "licence_expires_at": "2027-09-26",
                      "licence": {
                        "type": "multi_use_12m",
                        "reuse_until": "2027-09-26",
                        "resale_prohibited": true,
                        "permitted_channels": [
                          "email",
                          "telephone",
                          "post"
                        ],
                        "warranty_url": "https://emailmovers.com/trust/warranty",
                        "terms_version": "2026-09"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/orders/{id}/receipt": {
      "get": {
        "operationId": "getComplianceReceipt",
        "summary": "Get the compliance receipt",
        "description": "The order's compliance receipt as an ES256 JWS with its decoded claims and a PDF twin: records delivered, suppression removals, counts by subscriber class, TPS status and Article 14 status, the licence and the file hash.",
        "tags": [
          "Orders"
        ],
        "security": [
          {
            "OAuth2": [
              "orders:read"
            ]
          },
          {
            "ApiKey": [
              "orders:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "schema": {
              "type": "string",
              "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
              ]
            },
            "example": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
          }
        ],
        "responses": {
          "200": {
            "description": "The receipt.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComplianceReceipt"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Receipt for the Leeds order",
                    "value": {
                      "id": "rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R",
                      "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6InJjcHQtMjAyNi0wOSJ9.eyJyZWNlaXB0X2lkIjoicmNwdF8wMUpCNE5BMlE1VzhaQUs4UTJWN1hOM005UiJ9.MEUCIQDexampleSignatureOnly",
                      "alg": "ES256",
                      "kid": "rcpt-2026-09",
                      "jwks_url": "https://mydatahub.emailmovers.com/.well-known/jwks.json",
                      "pdf_url": "https://mydatahub.emailmovers.com/receipts/rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R",
                      "claims": {
                        "receipt_id": "rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R",
                        "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                        "issued_at": "2026-09-26T10:16:04Z",
                        "dataset_version": "2026-W39",
                        "records_delivered": 5000,
                        "removed_by_suppression": 41,
                        "counts": {
                          "subscriber_class": {
                            "ltd": 4610,
                            "plc": 120,
                            "llp": 180,
                            "scottish_partnership": 0,
                            "public_body": 60,
                            "charity_incorporated": 30,
                            "sole_trader": 0,
                            "ordinary_partnership": 0,
                            "unknown": 0
                          },
                          "tps_ctps_status": {
                            "clear": 4380,
                            "tps_registered": 0,
                            "ctps_registered": 0,
                            "tps_or_ctps_registered": 0,
                            "not_screened": 620
                          },
                          "article14_status": {
                            "notified": 4990,
                            "publicly_notified_disproportionate_effort": 0,
                            "pending_within_window": 10
                          }
                        },
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "lia_ref": "EM-LIA-2026-03",
                        "licence": {
                          "type": "multi_use_12m",
                          "reuse_until": "2027-09-26",
                          "resale_prohibited": true,
                          "permitted_channels": [
                            "email",
                            "telephone",
                            "post"
                          ],
                          "warranty_url": "https://emailmovers.com/trust/warranty",
                          "terms_version": "2026-09"
                        },
                        "residency_statement_version": "2026-10",
                        "sub_processor_list_version": "2026-10",
                        "verified_within_days": {
                          "within_30_days": 61.2,
                          "within_60_days": 79.5,
                          "within_90_days": 88.4
                        },
                        "content_sha256": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "get_compliance_receipt"
      }
    },
    "/orders/{id}/records": {
      "get": {
        "operationId": "listOrderRecords",
        "summary": "Fetch order records",
        "description": "Delivered records in token-budgeted pages (default 50, up to 500), as JSON with the licence block on every page or as CSV. Fetching again under licence costs 0 credits.",
        "tags": [
          "Records"
        ],
        "security": [
          {
            "OAuth2": [
              "records:read"
            ]
          },
          {
            "ApiKey": [
              "records:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "schema": {
              "type": "string",
              "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
              ]
            },
            "example": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Records per page, 1 to 500. Default 50.",
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            },
            "example": 50
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (default) or csv.",
            "schema": {
              "default": "json",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "description": "Columns to return, comma separated; default the order's field set.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "pattern": "^[a-z0-9_]+$"
              }
            },
            "style": "form",
            "explode": false
          }
        ],
        "responses": {
          "200": {
            "description": "A page of records.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordsPage"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The first page of the Leeds order",
                    "value": {
                      "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "format": "json",
                      "fields": [
                        "first_name",
                        "last_name",
                        "title",
                        "email",
                        "phone",
                        "company_name",
                        "postcode"
                      ],
                      "data": [
                        {
                          "id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                          "dataset_version": "2026-W39",
                          "contact": {
                            "first_name": "Jo",
                            "last_name": "Example",
                            "title": "Marketing Director",
                            "title_family": "Marketing Director",
                            "job_function": "Marketing",
                            "job_level_rank": 6,
                            "job_level": "Director"
                          },
                          "email": {
                            "address": "jo.example@example.co.uk",
                            "type": "named",
                            "deliverability_score": 88,
                            "verified_at": "2026-09-10",
                            "result": "ok"
                          },
                          "phone": {
                            "e164": "+441130000001",
                            "line_type": "landline",
                            "tps_ctps_status": "clear",
                            "screened_at": "2026-09-12"
                          },
                          "company": {
                            "name": "Example Manufacturing Ltd",
                            "companies_house_number": "12345678",
                            "status": "active",
                            "type": "ltd",
                            "subscriber_class": "ltd",
                            "sic_2007": [
                              {
                                "code": "25620",
                                "label": "Machining"
                              }
                            ],
                            "employee_band": "100-199",
                            "turnover_band": "11M-20M",
                            "website_domain": "example.co.uk"
                          },
                          "site": {
                            "address_lines": [
                              "1 Example Street"
                            ],
                            "town": "Leeds",
                            "county": "West Yorkshire",
                            "postcode": "LS11 5AA",
                            "region": "yorkshire_and_the_humber"
                          },
                          "compliance": {
                            "lawful_basis": "legitimate_interests_art6_1_f",
                            "lia_ref": "EM-LIA-2026-03",
                            "subscriber_class": "ltd",
                            "corporate_subscriber": true,
                            "email_marketing_basis": "pecr_corporate_subscriber",
                            "subscriber_evidence": {
                              "companies_house_number": "12345678",
                              "company_type": "ltd"
                            },
                            "article14_status": "notified",
                            "article14_notified_at": "2026-06-14",
                            "notice_version": "2026-02",
                            "provenance": {
                              "company": {
                                "source": "companies_house",
                                "as_of": "2026-09-21"
                              },
                              "contact": {
                                "source": "emailmovers_research",
                                "compiled_at": "2026-05-02",
                                "last_verified_at": "2026-08-30",
                                "method": "telephone"
                              },
                              "email": {
                                "verified_at": "2026-09-10",
                                "result": "ok",
                                "provider_location": "EU"
                              }
                            },
                            "tps_ctps_status": "clear",
                            "tps_ctps_screened_at": "2026-09-12",
                            "tps_ctps_valid_until": "2026-10-10",
                            "suppression_status": "none",
                            "record_age_days": 147,
                            "attribution": "Contains public sector information licensed under the Open Government Licence v3.0"
                          },
                          "licence_expires_at": "2027-09-26"
                        }
                      ],
                      "has_more": true,
                      "next_cursor": "b3JkXzAxSkI0TjlTM1cyWDZZN1o4QTFCMkMzRDRFOjUw",
                      "remaining": 4950,
                      "approx_tokens": 7400,
                      "licence": {
                        "type": "multi_use_12m",
                        "reuse_until": "2027-09-26",
                        "resale_prohibited": true,
                        "permitted_channels": [
                          "email",
                          "telephone",
                          "post"
                        ],
                        "warranty_url": "https://emailmovers.com/trust/warranty",
                        "terms_version": "2026-09"
                      }
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "CSV with a header row; compliance fields as columns."
                },
                "example": "mydatahub_record_id,first_name,last_name,title,email,company_name,postcode,lawful_basis,article14_status\ncontact_01JA9X2V7XN3M9R6T1Y5W8ZAK8,Jo,Example,Marketing Director,jo.example@example.co.uk,Example Manufacturing Ltd,LS11 5AA,legitimate_interests_art6_1_f,notified\n"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "fetch_order_records"
      }
    },
    "/orders/{id}/download": {
      "get": {
        "operationId": "downloadOrder",
        "summary": "Download order records",
        "description": "Redirects to a single-use signed URL for the CSV that lives 5 minutes, bound to the account and logged. Re-downloads under licence cost 0 credits.",
        "tags": [
          "Records"
        ],
        "security": [
          {
            "OAuth2": [
              "records:read"
            ]
          },
          {
            "ApiKey": [
              "records:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "schema": {
              "type": "string",
              "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
              ]
            },
            "example": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
          }
        ],
        "responses": {
          "302": {
            "description": "Found: follow Location to the signed file.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/companies/lookup": {
      "post": {
        "operationId": "lookupCompany",
        "summary": "Look up a company",
        "description": "Companies House fields for one company, by number, domain or name, and for signed-in callers the contacts we hold there by job level (a single company count needs an account and is logged; signed out, the counts are null). No contact details, and no charge (to confirm).",
        "tags": [
          "Lookups"
        ],
        "security": [
          {},
          {
            "OAuth2": [
              "counts:read"
            ]
          },
          {
            "ApiKey": [
              "counts:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyLookupRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "By Companies House number",
                  "value": {
                    "company_number": "12345678"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The company.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyLookup"
                },
                "examples": {
                  "illustrative": {
                    "summary": "By Companies House number",
                    "value": {
                      "match_confidence": 1,
                      "dataset_version": "2026-W39",
                      "company": {
                        "companies_house_number": "12345678",
                        "name": "Example Manufacturing Ltd",
                        "status": "active",
                        "type": "ltd",
                        "subscriber_class": "ltd",
                        "incorporation_date": "2004-02-19",
                        "sic_2007": [
                          {
                            "code": "25620",
                            "label": "Machining"
                          }
                        ],
                        "employee_band": "100-199",
                        "turnover_band": "11M-20M",
                        "website_domain": "example.co.uk",
                        "registered_office": {
                          "town": "Leeds",
                          "postcode": "LS11 5AA"
                        }
                      },
                      "contacts_held": 14,
                      "contacts_by_level": [
                        {
                          "level": "Director",
                          "contacts": 3
                        },
                        {
                          "level": "Manager",
                          "contacts": 6
                        }
                      ],
                      "compliance": {
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "subscriber_class": "ltd",
                        "corporate_subscriber": true,
                        "email_marketing_basis": "pecr_corporate_subscriber",
                        "subscriber_evidence": {
                          "companies_house_number": "12345678",
                          "company_type": "ltd"
                        },
                        "provenance": {
                          "company": {
                            "source": "companies_house",
                            "as_of": "2026-09-21"
                          }
                        },
                        "attribution": "Contains public sector information licensed under the Open Government Licence v3.0"
                      },
                      "disclosure": {
                        "level": "exact",
                        "rounded_to": null,
                        "secondary_suppression": false,
                        "notes": []
                      },
                      "credits_charged": 0
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true,
        "x-mcp-tool": "lookup_company"
      }
    },
    "/contacts/enrich": {
      "post": {
        "operationId": "enrichContact",
        "summary": "Enrich a contact (spends credits)",
        "description": "The full record for one known person, by email or by name and company. Charges 1 credit only on a confident match, and 0 when you already hold the record under licence or nothing matches. It spends, so it needs a human confirmation (MCP elicitation or a confirmation_token) or an agent key whose allowed_tools include enrich_contact, within its per-order cap and remaining monthly budget; otherwise 403 confirmation-required or agent-budget-exceeded, and 402 when the balance is short. An account made by self-serve sign-up confirms its business name and that it is a UK business first (PATCH /v1/account), or the answer is 403 business-details-required. The record comes under the Data Licence and Sharing Agreement, so the version in force is accepted as for an order, or the answer is 403 licence-acceptance-required with the approval_url. Nothing is charged on a refusal. Lawful basis for named work emails is UK GDPR Article 6(1)(f) legitimate interests; sole traders and ordinary partnerships are individual subscribers and are left out of email audiences by default.",
        "tags": [
          "Lookups"
        ],
        "security": [
          {
            "OAuth2": [
              "enrich:write"
            ]
          },
          {
            "ApiKey": [
              "enrich:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyRequired"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrichRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Enrich by name and company number",
                  "value": {
                    "first_name": "Jo",
                    "last_name": "Example",
                    "company_number": "12345678"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The match, or no match.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrichment"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Enrich by name and company number",
                    "value": {
                      "matched": true,
                      "match_confidence": 0.97,
                      "already_licensed": false,
                      "record": {
                        "id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                        "dataset_version": "2026-W39",
                        "contact": {
                          "first_name": "Jo",
                          "last_name": "Example",
                          "title": "Marketing Director",
                          "title_family": "Marketing Director",
                          "job_function": "Marketing",
                          "job_level_rank": 6,
                          "job_level": "Director"
                        },
                        "email": {
                          "address": "jo.example@example.co.uk",
                          "type": "named",
                          "deliverability_score": 88,
                          "verified_at": "2026-09-10",
                          "result": "ok"
                        },
                        "phone": {
                          "e164": "+441130000001",
                          "line_type": "landline",
                          "tps_ctps_status": "clear",
                          "screened_at": "2026-09-12"
                        },
                        "company": {
                          "name": "Example Manufacturing Ltd",
                          "companies_house_number": "12345678",
                          "status": "active",
                          "type": "ltd",
                          "subscriber_class": "ltd",
                          "sic_2007": [
                            {
                              "code": "25620",
                              "label": "Machining"
                            }
                          ],
                          "employee_band": "100-199",
                          "turnover_band": "11M-20M",
                          "website_domain": "example.co.uk"
                        },
                        "site": {
                          "address_lines": [
                            "1 Example Street"
                          ],
                          "town": "Leeds",
                          "county": "West Yorkshire",
                          "postcode": "LS11 5AA",
                          "region": "yorkshire_and_the_humber"
                        },
                        "compliance": {
                          "lawful_basis": "legitimate_interests_art6_1_f",
                          "lia_ref": "EM-LIA-2026-03",
                          "subscriber_class": "ltd",
                          "corporate_subscriber": true,
                          "email_marketing_basis": "pecr_corporate_subscriber",
                          "subscriber_evidence": {
                            "companies_house_number": "12345678",
                            "company_type": "ltd"
                          },
                          "article14_status": "notified",
                          "article14_notified_at": "2026-06-14",
                          "notice_version": "2026-02",
                          "provenance": {
                            "company": {
                              "source": "companies_house",
                              "as_of": "2026-09-21"
                            },
                            "contact": {
                              "source": "emailmovers_research",
                              "compiled_at": "2026-05-02",
                              "last_verified_at": "2026-08-30",
                              "method": "telephone"
                            },
                            "email": {
                              "verified_at": "2026-09-10",
                              "result": "ok",
                              "provider_location": "EU"
                            }
                          },
                          "tps_ctps_status": "clear",
                          "tps_ctps_screened_at": "2026-09-12",
                          "tps_ctps_valid_until": "2026-10-10",
                          "suppression_status": "none",
                          "record_age_days": 147,
                          "attribution": "Contains public sector information licensed under the Open Government Licence v3.0"
                        },
                        "licence_expires_at": "2027-09-26"
                      },
                      "credits_charged": 1,
                      "credits_remaining": 1199,
                      "cost_gbp": 0.3,
                      "licence_expires_at": "2027-09-26"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 1,
        "x-cost-unit": "match",
        "x-cost-note": "1 credit on a confident match; 0 on no match or when already licensed.",
        "x-free": false,
        "x-anonymous": false,
        "x-idempotency-key": "required",
        "x-mcp-tool": "enrich_contact"
      }
    },
    "/suppressions": {
      "get": {
        "operationId": "listSuppressions",
        "summary": "List suppression lists",
        "description": "The organisation's suppression lists. With since, only lists changed after that time, each with the records added since, so objections that reach records you hold can be pulled as well as received by webhook.",
        "tags": [
          "Suppressions"
        ],
        "security": [
          {
            "OAuth2": [
              "suppressions:read"
            ]
          },
          {
            "ApiKey": [
              "suppressions:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only lists changed after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of suppression lists.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuppressionListPage"
                },
                "examples": {
                  "illustrative": {
                    "summary": "One uploaded list",
                    "value": {
                      "data": [
                        {
                          "id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA",
                          "name": "Existing customers",
                          "kind": "email",
                          "source": "upload",
                          "row_count": 1198,
                          "created_at": "2026-09-20T14:02:00Z",
                          "updated_at": "2026-09-20T14:02:00Z",
                          "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      },
      "post": {
        "operationId": "createSuppressionList",
        "summary": "Upload a suppression list",
        "description": "Upload emails, domains, phones, company numbers or title terms, raw or already hashed. Values are normalised and stored as SHA-256 hashes only. The list applies to every later count and order at no charge, and each count reports what it removed. The organisation accepts the Article 28 data processing agreement in force first (POST /v1/account/agreements, or dpa_accepted_version on this upload from a signed-in person); until then the answer is 403 dpa-acceptance-required and nothing is uploaded.",
        "tags": [
          "Suppressions"
        ],
        "security": [
          {
            "OAuth2": [
              "suppressions:write"
            ]
          },
          {
            "ApiKey": [
              "suppressions:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuppressionListRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Upload existing customers",
                  "value": {
                    "name": "Existing customers",
                    "kind": "email",
                    "values": [
                      "jo.example@example.co.uk",
                      "sam@example.org"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The saved list and what was read.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuppressionUpload"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Upload existing customers",
                    "value": {
                      "list": {
                        "id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA",
                        "name": "Existing customers",
                        "kind": "email",
                        "source": "upload",
                        "row_count": 1198,
                        "created_at": "2026-09-20T14:02:00Z",
                        "updated_at": "2026-09-20T14:02:00Z",
                        "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
                      },
                      "rows_read": 1204,
                      "rows_valid": 1198,
                      "rows_skipped": [
                        {
                          "row": 17,
                          "reason": "Not an email address."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/suppressions/check": {
      "post": {
        "operationId": "checkSuppression",
        "summary": "Check suppression",
        "description": "Suppression status per record id, as of now. Run it before any send.",
        "tags": [
          "Suppressions"
        ],
        "security": [
          {
            "OAuth2": [
              "suppressions:read"
            ]
          },
          {
            "ApiKey": [
              "suppressions:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuppressionCheckRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Check one record",
                  "value": {
                    "record_ids": [
                      "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Status per record.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuppressionCheck"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Check one record",
                    "value": {
                      "checked_at": "2026-10-01T09:00:00Z",
                      "results": [
                        {
                          "record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                          "suppressed": false,
                          "suppression_status": "none",
                          "list_ids": []
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "check_suppression"
      }
    },
    "/objections": {
      "post": {
        "operationId": "reportObjection",
        "summary": "Report an objection",
        "description": "Record an objection to direct marketing. Scope licensee suppresses the record for your organisation at once; scope emailmovers suppresses it database-wide within one working day and tells every licensee holding it.",
        "tags": [
          "Suppressions"
        ],
        "security": [
          {
            "OAuth2": [
              "suppressions:write"
            ]
          },
          {
            "ApiKey": [
              "suppressions:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ObjectionRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "An objection received by email",
                  "value": {
                    "record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                    "channel": "email",
                    "received_at": "2026-10-01T08:30:00Z",
                    "scope": "emailmovers",
                    "note": "Replied asking not to be contacted again."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The suppression it created.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Objection"
                },
                "examples": {
                  "illustrative": {
                    "summary": "An objection received by email",
                    "value": {
                      "suppression_id": "sup_01JA0Q5V7XN3M9R6T1Y5W8ZAK8",
                      "record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                      "scope": "emailmovers",
                      "status": "pending",
                      "suppressed_at": null,
                      "effective_by": "2026-10-02T17:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional",
        "x-mcp-tool": "report_objection"
      }
    },
    "/trust": {
      "get": {
        "operationId": "getTrust",
        "summary": "Get the trust document",
        "description": "The trust page as data: ICO registration, lawful basis and LIA, privacy notice, residency statement, sub-processors, retention, complaints and security. Mirrored at https://mydatahub.emailmovers.com/trust.json.",
        "tags": [
          "Compliance"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "The trust document.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrustDocument"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The trust document",
                    "value": {
                      "updated_at": "2026-09-26T09:00:00Z",
                      "company": {
                        "legal_name": "Emailmovers Limited",
                        "company_number": "05046417",
                        "trading_as": "Emailmovers Ltd"
                      },
                      "ico_registration": {
                        "number": "Z9714386",
                        "expires_on": "2026-12-18",
                        "register_url": "https://ico.org.uk/ESDWebPages/Entry/Z9714386"
                      },
                      "lawful_basis": {
                        "basis": "legitimate_interests_art6_1_f",
                        "lia_ref": "EM-LIA-2026-03",
                        "lia_url": "https://emailmovers.com/trust/lia"
                      },
                      "privacy_notice": {
                        "version": "2026-02",
                        "url": "https://emailmovers.com/trust/privacy-notice",
                        "versions": [
                          {
                            "version": "2026-02",
                            "published_at": "2026-02-05",
                            "url": "https://emailmovers.com/trust/privacy-notice/2026-02"
                          }
                        ]
                      },
                      "residency": {
                        "statement": "Data is held in the UK (Google Cloud London). Email addresses are verified in the EU by Millionverifier, with some verification traffic passing through US providers under standard contractual clauses. Telephone numbers are checked by Telnyx in the United States under the UK Extension to the Data Privacy Framework. Every telephone number is screened against the TPS and CTPS each night through a licensed screening service based in the UK, which processes the numbers in the UK. Payments are processed by Stripe.",
                        "version": "2026-10"
                      },
                      "sub_processors": {
                        "version": "2026-10",
                        "notice_days": 30,
                        "notice_channels": [
                          "email",
                          "webhook"
                        ],
                        "list": [
                          {
                            "name": "Millionverifier",
                            "purpose": "Email verification",
                            "location": "EU (Hungary), some US network traffic",
                            "transfer_mechanism": "Standard contractual clauses",
                            "added_at": "2026-09-01"
                          },
                          {
                            "name": "Telnyx",
                            "purpose": "Telephone line type checks",
                            "location": "United States",
                            "transfer_mechanism": "UK Extension to the Data Privacy Framework",
                            "added_at": "2026-09-01"
                          },
                          {
                            "name": "A licensed TPS and CTPS screening service",
                            "purpose": "TPS and CTPS screening of every telephone number each night",
                            "location": "United Kingdom",
                            "transfer_mechanism": "No transfer outside the UK",
                            "added_at": "2026-10-18"
                          }
                        ],
                        "changes": [
                          {
                            "date": "2026-09-01",
                            "name": "Telnyx",
                            "change": "added",
                            "summary": "Telephone line type and carrier checks at ingest and every 180 days."
                          },
                          {
                            "date": "2026-10-18",
                            "name": "A licensed TPS and CTPS screening service",
                            "change": "added",
                            "summary": "Every telephone number screened against the TPS and CTPS each night, in the UK."
                          }
                        ]
                      },
                      "retention": [
                        {
                          "category": "Audit logs",
                          "period": "Licence term plus 12 months",
                          "status": "to_confirm"
                        }
                      ],
                      "complaints": {
                        "url": "https://emailmovers.com/trust/complaints",
                        "email": null,
                        "acknowledgement_days": 30
                      },
                      "data_protection_lead": null,
                      "datasets": [
                        {
                          "id": "uk_contacts",
                          "name": "UK contacts",
                          "status": "live",
                          "owner": "Emailmovers Ltd",
                          "source": "Emailmovers research; Companies House (OGL v3.0); ONSPD (OGL v3.0)",
                          "licence": "12 month multi-use licence; resale prohibited",
                          "refresh": "Immutable weekly build every Monday; same-day suppression overlay",
                          "residency": "Held in the UK (Google Cloud London)",
                          "regulator": "ICO",
                          "warranty": "Replacement when hard bounces exceed 10 percent of an order",
                          "credits_per_record": 1,
                          "credits_status": "confirmed",
                          "current_version": "2026-W39",
                          "versions_available": 52
                        }
                      ],
                      "security": {
                        "certifications": [
                          {
                            "name": "Cyber Essentials",
                            "status": "target",
                            "date": "2026-10"
                          },
                          {
                            "name": "Cyber Essentials Plus",
                            "status": "target",
                            "date": "2027-01"
                          }
                        ],
                        "encryption": {
                          "at_rest": "AES-256",
                          "in_transit_minimum": "TLS 1.2",
                          "key_rotation": "KMS managed key rotation"
                        },
                        "data_flow_diagram_url": null,
                        "pen_test_summary_url": null,
                        "caiq_url": null,
                        "status_page": "https://status.emailmovers.com",
                        "security_txt": "https://mydatahub.emailmovers.com/.well-known/security.txt"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/compliance/lia": {
      "get": {
        "operationId": "getLia",
        "summary": "Get the legitimate interests assessment",
        "description": "The published LIA (EM-LIA-2026-03) with its version history.",
        "tags": [
          "Compliance"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "The LIA.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiaDocument"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The current LIA",
                    "value": {
                      "ref": "EM-LIA-2026-03",
                      "version": "2026-03",
                      "published_at": "2026-11-30",
                      "url": "https://emailmovers.com/trust/lia",
                      "lawful_basis": "legitimate_interests_art6_1_f",
                      "summary": "Emailmovers relies on UK GDPR Article 6(1)(f) legitimate interests for named business contacts, with direct marketing as an Article 6(1)(f) example since 5 February 2026.",
                      "versions": [
                        {
                          "ref": "EM-LIA-2026-03",
                          "published_at": "2026-11-30",
                          "url": "https://emailmovers.com/trust/lia"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/compliance/receipts/verify": {
      "post": {
        "operationId": "verifyComplianceReceipt",
        "summary": "Verify a compliance receipt",
        "description": "Check a receipt's JWS against the published key without an account, and learn whether the order exists, until when its licence is in force and whether it was revoked. One agent can prove to another that a list is licensed and screened. REST only.",
        "tags": [
          "Compliance"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceiptVerifyRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "A valid receipt",
                  "value": {
                    "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6InJjcHQtMjAyNi0wOSJ9.eyJyZWNlaXB0X2lkIjoicmNwdF8wMUpCNE5BMlE1VzhaQUs4UTJWN1hOM005UiJ9.MEUCIQDexampleSignatureOnly"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The verdict.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceiptVerification"
                },
                "examples": {
                  "illustrative": {
                    "summary": "A valid receipt",
                    "value": {
                      "valid": true,
                      "order_exists": true,
                      "licence_in_force_until": "2027-09-26",
                      "revoked": false,
                      "receipt_id": "rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R",
                      "checked_at": "2026-10-01T09:00:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/account": {
      "get": {
        "operationId": "getAccount",
        "summary": "Get the account",
        "description": "Balance by source, plan, per-action prices, the rate limit and, for an agent key, its budget and per-order cap.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "account:read"
            ]
          },
          {
            "ApiKey": [
              "account:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "The account.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Called with an agent key",
                    "value": {
                      "organisation": {
                        "id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                        "name": "Example Agency Ltd",
                        "business_details": {
                          "confirmed_at": null,
                          "required_before_order": false,
                          "name_editable": false
                        }
                      },
                      "user": null,
                      "mode": "live",
                      "plan": {
                        "id": "pay_as_you_go",
                        "name": "Pay as you go",
                        "kind": "subscription",
                        "renews_at": "2026-10-26",
                        "cancel_at_period_end": false
                      },
                      "balance": {
                        "credits": 6200,
                        "pack_credits": 5000,
                        "subscription_credits": 1200,
                        "rollover_cap": 12000,
                        "low_threshold": 500
                      },
                      "prices": [
                        {
                          "action": "count",
                          "label": "Count, breakdown, preview, machine quote, catalogue, title expansion",
                          "credits": 0,
                          "unit": "call",
                          "status": "confirmed"
                        },
                        {
                          "action": "record",
                          "label": "Full UK contact record delivered, any channel or field set",
                          "credits": 1,
                          "unit": "record",
                          "status": "confirmed"
                        },
                        {
                          "action": "company_only_record",
                          "label": "Company-only record (no named contact)",
                          "credits": 0.1,
                          "unit": "record",
                          "status": "proposed"
                        },
                        {
                          "action": "enrich_contact",
                          "label": "Contact enrichment, match found",
                          "credits": 1,
                          "unit": "match",
                          "status": "confirmed",
                          "note": "0 if already licensed"
                        },
                        {
                          "action": "lookup_company",
                          "label": "Company lookup, no contact details",
                          "credits": 0,
                          "unit": "call",
                          "status": "to_confirm"
                        },
                        {
                          "action": "outright",
                          "label": "Outright ownership",
                          "credits": 1.8,
                          "unit": "record",
                          "status": "proposed"
                        }
                      ],
                      "gbp_per_credit": 0.299,
                      "rate_limit": {
                        "tier": "paid",
                        "counts_per_minute": 600,
                        "counts_per_hour": null,
                        "counts_per_day": null,
                        "remaining": 598,
                        "resets_at": "2026-09-26T10:15:00Z",
                        "status": "to_confirm"
                      },
                      "key": {
                        "id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
                        "kind": "agent",
                        "budget": {
                          "monthly_credits": 1000,
                          "spent": 400,
                          "remaining": 600,
                          "resets_at": "2026-10-01T00:00:00Z"
                        },
                        "per_order_max_credits": 500,
                        "expires_at": "2027-03-31T00:00:00Z"
                      },
                      "account_manager": {
                        "name": "Jordan Hale",
                        "calendar_url": "https://emailmovers.com/talk-to-us"
                      },
                      "agreements": {
                        "dlsa": {
                          "name": "Data Licence and Sharing Agreement",
                          "version": "1.0",
                          "url": "https://emailmovers.com/data-licence/",
                          "accepted": {
                            "version": "1.0",
                            "accepted_at": "2026-11-02T10:12:00Z",
                            "accepted_by": "usr_01JB4H8Q2V7XN3M9R6T1Y5W8ZA"
                          }
                        },
                        "dpa": {
                          "name": "Article 28 data processing agreement",
                          "version": "1.0",
                          "url": "https://emailmovers.com/dpa/",
                          "accepted": null
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-mcp-tool": "get_account"
      },
      "patch": {
        "operationId": "updateAccount",
        "summary": "Confirm the business details",
        "description": "Set the organisation's business name and confirm that it is a UK business. An organisation made by self-serve sign-up needs both before its first order or enrichment, free or paid: until then POST /v1/orders and POST /v1/contacts/enrich answer 403 business-details-required and charge nothing. A signed-in person who owns the account confirms them, through OAuth (with account:write, or admin) or in the app; an API key cannot. An organisation Emailmovers set up keeps the name staff gave it and needs no business details, so it is refused with 422 (organisation.business_details.name_editable is false).",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "account:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountUpdateRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Confirm the business name and that it is a UK business",
                  "value": {
                    "business_name": "Example Trading Ltd",
                    "uk_business": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The account.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Confirm the business name and that it is a UK business",
                    "value": {
                      "organisation": {
                        "id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                        "name": "Example Trading Ltd",
                        "business_details": {
                          "confirmed_at": "2026-10-18T09:30:00Z",
                          "required_before_order": false,
                          "name_editable": true
                        }
                      },
                      "user": {
                        "id": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                        "name": "jo@example-trading.co.uk"
                      },
                      "mode": "live",
                      "plan": {
                        "id": "free",
                        "name": "Free",
                        "kind": "free",
                        "renews_at": null,
                        "cancel_at_period_end": false
                      },
                      "balance": {
                        "credits": 100,
                        "pack_credits": 100,
                        "subscription_credits": 0,
                        "rollover_cap": null,
                        "low_threshold": null
                      },
                      "prices": [
                        {
                          "action": "count",
                          "label": "Count, breakdown, preview, machine quote, catalogue, title expansion",
                          "credits": 0,
                          "unit": "call",
                          "status": "confirmed"
                        },
                        {
                          "action": "record",
                          "label": "Full UK contact record delivered, any channel or field set",
                          "credits": 1,
                          "unit": "record",
                          "status": "confirmed"
                        },
                        {
                          "action": "company_only_record",
                          "label": "Company-only record (no named contact)",
                          "credits": 0.1,
                          "unit": "record",
                          "status": "proposed"
                        },
                        {
                          "action": "enrich_contact",
                          "label": "Contact enrichment, match found",
                          "credits": 1,
                          "unit": "match",
                          "status": "confirmed",
                          "note": "0 if already licensed"
                        },
                        {
                          "action": "lookup_company",
                          "label": "Company lookup, no contact details",
                          "credits": 0,
                          "unit": "call",
                          "status": "to_confirm"
                        },
                        {
                          "action": "outright",
                          "label": "Outright ownership",
                          "credits": 1.8,
                          "unit": "record",
                          "status": "proposed"
                        }
                      ],
                      "gbp_per_credit": 0.299,
                      "rate_limit": {
                        "tier": "free",
                        "counts_per_minute": 60,
                        "counts_per_hour": null,
                        "counts_per_day": 1000,
                        "remaining": 59,
                        "resets_at": "2026-09-26T10:15:00Z",
                        "status": "to_confirm"
                      },
                      "key": null,
                      "account_manager": null,
                      "agreements": {
                        "dlsa": {
                          "name": "Data Licence and Sharing Agreement",
                          "version": "1.0",
                          "url": "https://emailmovers.com/data-licence/",
                          "accepted": {
                            "version": "1.0",
                            "accepted_at": "2026-11-02T10:12:00Z",
                            "accepted_by": "usr_01JB4H8Q2V7XN3M9R6T1Y5W8ZA"
                          }
                        },
                        "dpa": {
                          "name": "Article 28 data processing agreement",
                          "version": "1.0",
                          "url": "https://emailmovers.com/dpa/",
                          "accepted": null
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/account/agreements": {
      "post": {
        "operationId": "acceptAccountAgreements",
        "summary": "Accept the data processing agreement",
        "description": "Accept the Article 28 data processing agreement at the version in force (the account's agreements.dpa). A suppression upload needs it first: until it is accepted POST /v1/suppressions answers 403 dpa-acceptance-required and uploads nothing, unless a person accepts it with that upload. A signed-in person who owns the account accepts it, through OAuth (with account:write, or admin) or in the app's Settings; an API key cannot. The account keeps the version, the person and the time, and a later version is accepted again.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "account:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountAgreementsRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Accept the data processing agreement",
                  "value": {
                    "dpa_accepted_version": "1.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The account, with its agreements.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Accept the data processing agreement",
                    "value": {
                      "organisation": {
                        "id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                        "name": "Example Agency Ltd",
                        "business_details": {
                          "confirmed_at": null,
                          "required_before_order": false,
                          "name_editable": false
                        }
                      },
                      "user": null,
                      "mode": "live",
                      "plan": {
                        "id": "pay_as_you_go",
                        "name": "Pay as you go",
                        "kind": "subscription",
                        "renews_at": "2026-10-26",
                        "cancel_at_period_end": false
                      },
                      "balance": {
                        "credits": 6200,
                        "pack_credits": 5000,
                        "subscription_credits": 1200,
                        "rollover_cap": 12000,
                        "low_threshold": 500
                      },
                      "prices": [
                        {
                          "action": "count",
                          "label": "Count, breakdown, preview, machine quote, catalogue, title expansion",
                          "credits": 0,
                          "unit": "call",
                          "status": "confirmed"
                        },
                        {
                          "action": "record",
                          "label": "Full UK contact record delivered, any channel or field set",
                          "credits": 1,
                          "unit": "record",
                          "status": "confirmed"
                        },
                        {
                          "action": "company_only_record",
                          "label": "Company-only record (no named contact)",
                          "credits": 0.1,
                          "unit": "record",
                          "status": "proposed"
                        },
                        {
                          "action": "enrich_contact",
                          "label": "Contact enrichment, match found",
                          "credits": 1,
                          "unit": "match",
                          "status": "confirmed",
                          "note": "0 if already licensed"
                        },
                        {
                          "action": "lookup_company",
                          "label": "Company lookup, no contact details",
                          "credits": 0,
                          "unit": "call",
                          "status": "to_confirm"
                        },
                        {
                          "action": "outright",
                          "label": "Outright ownership",
                          "credits": 1.8,
                          "unit": "record",
                          "status": "proposed"
                        }
                      ],
                      "gbp_per_credit": 0.299,
                      "rate_limit": {
                        "tier": "paid",
                        "counts_per_minute": 600,
                        "counts_per_hour": null,
                        "counts_per_day": null,
                        "remaining": 598,
                        "resets_at": "2026-09-26T10:15:00Z",
                        "status": "to_confirm"
                      },
                      "key": {
                        "id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
                        "kind": "agent",
                        "budget": {
                          "monthly_credits": 1000,
                          "spent": 400,
                          "remaining": 600,
                          "resets_at": "2026-10-01T00:00:00Z"
                        },
                        "per_order_max_credits": 500,
                        "expires_at": "2027-03-31T00:00:00Z"
                      },
                      "account_manager": {
                        "name": "Jordan Hale",
                        "calendar_url": "https://emailmovers.com/talk-to-us"
                      },
                      "agreements": {
                        "dlsa": {
                          "name": "Data Licence and Sharing Agreement",
                          "version": "1.0",
                          "url": "https://emailmovers.com/data-licence/",
                          "accepted": {
                            "version": "1.0",
                            "accepted_at": "2026-11-02T10:12:00Z",
                            "accepted_by": "usr_01JB4H8Q2V7XN3M9R6T1Y5W8ZA"
                          }
                        },
                        "dpa": {
                          "name": "Article 28 data processing agreement",
                          "version": "1.0",
                          "url": "https://emailmovers.com/dpa/",
                          "accepted": {
                            "version": "1.0",
                            "accepted_at": "2026-11-03T09:00:00Z",
                            "accepted_by": "usr_01JB4H8Q2V7XN3M9R6T1Y5W8ZA"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/account/usage": {
      "get": {
        "operationId": "getAccountUsage",
        "summary": "Get account usage",
        "description": "Credits charged, refunded and added in a period, by action and by key.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "account:read"
            ]
          },
          {
            "ApiKey": [
              "account:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day, inclusive. Default 30 days ago.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-09-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day, inclusive. Default today.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-09-30"
          }
        ],
        "responses": {
          "200": {
            "description": "Usage in the period.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountUsage"
                },
                "examples": {
                  "illustrative": {
                    "summary": "September 2026",
                    "value": {
                      "from": "2026-09-01",
                      "to": "2026-09-30",
                      "credits_charged": 5400,
                      "credits_refunded": 0,
                      "credits_added": 6000,
                      "by_action": [
                        {
                          "action": "count",
                          "calls": 1840,
                          "credits": 0
                        },
                        {
                          "action": "record",
                          "calls": 2,
                          "credits": 5400
                        }
                      ],
                      "by_key": [
                        {
                          "key_id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
                          "label": "SDR agent",
                          "credits": 400
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/account/cancel": {
      "post": {
        "operationId": "cancelAccount",
        "summary": "Cancel the plan",
        "description": "End a rolling plan at the end of its period, in one call, with no reason required; any notice terms in your agreement still apply. Credit pack credits never expire and survive cancellation, and delivered records stay licensed to the end of their term.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "admin"
            ]
          },
          {
            "ApiKey": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountCancellationRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Cancel pay as you go",
                  "value": {
                    "reason": "Campaign finished."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "When the plan ends and what is kept.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCancellation"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Cancel pay as you go",
                    "value": {
                      "plan": "pay_as_you_go",
                      "cancel_at_period_end": true,
                      "ends_at": "2026-10-26",
                      "pack_credits_kept": 5000,
                      "subscription_credits_usable_until": "2026-10-26",
                      "licences_unaffected": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/account/purchases": {
      "post": {
        "operationId": "createCreditPurchase",
        "summary": "Buy credits by card",
        "description": "Start a card payment in Stripe Checkout for credits at the per-contact scale (the size of the line picks its band), the 40,000 credit pack, or a quote's purchase option line by line. Prices exclude VAT; 20 percent UK VAT is added at checkout, which takes cards only (Apple Pay and Google Pay through the card method) and a UK billing address. Answers with the checkout_url to send the person to. The credits are added once, when Stripe says the payment is paid. Credits and credit packs are not refundable once bought, except where the law requires. A signed-in person with the admin scope buys; an API key cannot. The subscription is not bought here. 503 when card payments are not switched on.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreditPurchaseRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Buy the 40,000 credit pack",
                  "value": {
                    "lines": [
                      {
                        "id": "credit_pack_40000",
                        "quantity": 1
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The pending purchase and its checkout_url.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditPurchase"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Buy the 40,000 credit pack",
                    "value": {
                      "id": "pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA",
                      "label": "1 credit pack of 40,000",
                      "lines": [
                        {
                          "id": "credit_pack_40000",
                          "quantity": 1,
                          "credits": 40000,
                          "gbp_ex_vat": 1249
                        }
                      ],
                      "credits": 40000,
                      "gbp_ex_vat": 1249,
                      "vat_rate_percent": 20,
                      "vat_gbp": 249.8,
                      "total_gbp": 1498.8,
                      "currency": "GBP",
                      "gbp_per_credit": 0.031225,
                      "test_mode": true,
                      "created_at": "2026-10-16T10:00:00Z",
                      "expires_at": "2026-10-17T10:00:00Z",
                      "attention": null,
                      "status": "pending",
                      "credits_added": 0,
                      "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_EXAMPLE",
                      "paid_at": null,
                      "receipt": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      },
      "get": {
        "operationId": "listCreditPurchases",
        "summary": "List credit purchases",
        "description": "Credits bought by card, newest first, each with its price excluding VAT, the VAT, the total and, once paid, its payment receipt. payments says whether card payments are switched on here and whether they are Stripe test mode.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "account:read"
            ]
          },
          {
            "ApiKey": [
              "account:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of credit purchases.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditPurchaseList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "One paid credit pack",
                    "value": {
                      "data": [
                        {
                          "id": "pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA",
                          "label": "1 credit pack of 40,000",
                          "lines": [
                            {
                              "id": "credit_pack_40000",
                              "quantity": 1,
                              "credits": 40000,
                              "gbp_ex_vat": 1249
                            }
                          ],
                          "credits": 40000,
                          "gbp_ex_vat": 1249,
                          "vat_rate_percent": 20,
                          "vat_gbp": 249.8,
                          "total_gbp": 1498.8,
                          "currency": "GBP",
                          "gbp_per_credit": 0.031225,
                          "test_mode": true,
                          "created_at": "2026-10-16T10:00:00Z",
                          "expires_at": "2026-10-17T10:00:00Z",
                          "attention": null,
                          "status": "paid",
                          "credits_added": 40000,
                          "checkout_url": null,
                          "paid_at": "2026-10-16T10:03:12Z",
                          "receipt": {
                            "number": "MDH-000042",
                            "issued_at": "2026-10-16T10:03:12Z",
                            "supplier": {
                              "name": "Example Supplier Limited",
                              "company_number": "00000000",
                              "registered_office": "1 Example Street, Exampletown, EX1 1EX, England",
                              "vat_number": "GB000000000"
                            },
                            "customer": {
                              "organisation_id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                              "organisation_name": "Example Agency Ltd",
                              "business_name": "Example Agency Ltd",
                              "name": "Example Agency Ltd",
                              "address": {
                                "line1": "2 Sample Road",
                                "line2": null,
                                "city": "Exampletown",
                                "postal_code": "EX2 2EX",
                                "state": null,
                                "country": "GB"
                              },
                              "vat_number": "GB999999999"
                            },
                            "description": "1 credit pack of 40,000",
                            "credits": 40000,
                            "gbp_per_credit": 0.031225,
                            "gbp_ex_vat": 1249,
                            "vat_rate_percent": 20,
                            "vat_gbp": 249.8,
                            "total_gbp": 1498.8,
                            "paid_by": "card",
                            "payment_reference": "pi_test_EXAMPLE",
                            "refunds": "Credits and credit packs are not refundable once bought, except where the law requires.",
                            "test_mode": true
                          }
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null,
                      "payments": {
                        "available": true,
                        "test_mode": true,
                        "vat_rate_percent": 20
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/account/purchases/{id}": {
      "get": {
        "operationId": "getCreditPurchase",
        "summary": "Get a credit purchase",
        "description": "One purchase of credits by card. Reading a pending purchase asks Stripe for its checkout and, once the payment is paid, adds the credits exactly once and writes the payment receipt, so the page Checkout returns to can show the credits added. Until then it stays pending. 503 when card payments are switched off and the purchase is still pending.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "OAuth2": [
              "account:read"
            ]
          },
          {
            "ApiKey": [
              "account:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a credit purchase id: pur_ followed by a 26 character ULID in upper case Crockford base32, such as pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^pur_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA"
          }
        ],
        "responses": {
          "200": {
            "description": "The purchase.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditPurchase"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Paid, with its receipt",
                    "value": {
                      "id": "pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA",
                      "label": "1 credit pack of 40,000",
                      "lines": [
                        {
                          "id": "credit_pack_40000",
                          "quantity": 1,
                          "credits": 40000,
                          "gbp_ex_vat": 1249
                        }
                      ],
                      "credits": 40000,
                      "gbp_ex_vat": 1249,
                      "vat_rate_percent": 20,
                      "vat_gbp": 249.8,
                      "total_gbp": 1498.8,
                      "currency": "GBP",
                      "gbp_per_credit": 0.031225,
                      "test_mode": true,
                      "created_at": "2026-10-16T10:00:00Z",
                      "expires_at": "2026-10-17T10:00:00Z",
                      "attention": null,
                      "status": "paid",
                      "credits_added": 40000,
                      "checkout_url": null,
                      "paid_at": "2026-10-16T10:03:12Z",
                      "receipt": {
                        "number": "MDH-000042",
                        "issued_at": "2026-10-16T10:03:12Z",
                        "supplier": {
                          "name": "Example Supplier Limited",
                          "company_number": "00000000",
                          "registered_office": "1 Example Street, Exampletown, EX1 1EX, England",
                          "vat_number": "GB000000000"
                        },
                        "customer": {
                          "organisation_id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                          "organisation_name": "Example Agency Ltd",
                          "business_name": "Example Agency Ltd",
                          "name": "Example Agency Ltd",
                          "address": {
                            "line1": "2 Sample Road",
                            "line2": null,
                            "city": "Exampletown",
                            "postal_code": "EX2 2EX",
                            "state": null,
                            "country": "GB"
                          },
                          "vat_number": "GB999999999"
                        },
                        "description": "1 credit pack of 40,000",
                        "credits": 40000,
                        "gbp_per_credit": 0.031225,
                        "gbp_ex_vat": 1249,
                        "vat_rate_percent": 20,
                        "vat_gbp": 249.8,
                        "total_gbp": 1498.8,
                        "paid_by": "card",
                        "payment_reference": "pi_test_EXAMPLE",
                        "refunds": "Credits and credit packs are not refundable once bought, except where the law requires.",
                        "test_mode": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/api-keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "API keys and agent keys, with each agent key's live spend meter. Secrets are never shown again.",
        "tags": [
          "Keys"
        ],
        "security": [
          {
            "OAuth2": [
              "admin"
            ]
          },
          {
            "ApiKey": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of keys.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "One agent key",
                    "value": {
                      "data": [
                        {
                          "id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
                          "kind": "agent",
                          "label": "SDR agent",
                          "mode": "live",
                          "prefix": "mdh_live_7Kq2",
                          "scopes": [
                            "counts:read",
                            "quotes:read",
                            "orders:write",
                            "orders:read",
                            "records:read",
                            "pushes:write"
                          ],
                          "ip_allowlist": [],
                          "created_at": "2026-09-20T09:00:00Z",
                          "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                          "last_used_at": "2026-09-26T02:00:00Z",
                          "expires_at": "2027-03-31T00:00:00Z",
                          "revoked_at": null,
                          "allowed_tools": [
                            "count_audience",
                            "quote_order",
                            "create_order",
                            "fetch_order_records",
                            "push_to_crm"
                          ],
                          "allowed_connection_ids": [
                            "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
                          ],
                          "monthly_budget_credits": 1000,
                          "per_order_max_credits": 500,
                          "budget": {
                            "monthly_credits": 1000,
                            "spent": 400,
                            "remaining": 600,
                            "resets_at": "2026-10-01T00:00:00Z"
                          },
                          "webhook_url": "https://agent.example.com/mydatahub/events",
                          "disclosure": "account"
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Create a standard key or an agent key. An agent key has a label, allowed tools, a monthly budget, a per-order cap, an expiry and a webhook, and is created by a signed-in person through OAuth, never by a key. An agent key needs allowed_tools and per_order_max_credits and never takes admin. Unlimited keys on every plan; the secret is shown once.",
        "tags": [
          "Keys"
        ],
        "security": [
          {
            "OAuth2": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "An agent key with a 1,000 credit monthly budget",
                  "value": {
                    "kind": "agent",
                    "label": "SDR agent",
                    "scopes": [
                      "counts:read",
                      "quotes:read",
                      "orders:write",
                      "orders:read",
                      "records:read",
                      "pushes:write"
                    ],
                    "allowed_tools": [
                      "count_audience",
                      "quote_order",
                      "create_order",
                      "fetch_order_records",
                      "push_to_crm"
                    ],
                    "allowed_connection_ids": [
                      "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
                    ],
                    "monthly_budget_credits": 1000,
                    "per_order_max_credits": 500,
                    "expires_at": "2027-03-31T00:00:00Z",
                    "licence_accepted_version": "1.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The key and its secret.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreated"
                },
                "examples": {
                  "illustrative": {
                    "summary": "An agent key with a 1,000 credit monthly budget",
                    "value": {
                      "key": {
                        "id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
                        "kind": "agent",
                        "label": "SDR agent",
                        "mode": "test",
                        "prefix": "mdh_test_Exam",
                        "scopes": [
                          "counts:read",
                          "quotes:read",
                          "orders:write",
                          "orders:read",
                          "records:read",
                          "pushes:write"
                        ],
                        "ip_allowlist": [],
                        "created_at": "2026-09-20T09:00:00Z",
                        "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                        "last_used_at": "2026-09-26T02:00:00Z",
                        "expires_at": "2027-03-31T00:00:00Z",
                        "revoked_at": null,
                        "allowed_tools": [
                          "count_audience",
                          "quote_order",
                          "create_order",
                          "fetch_order_records",
                          "push_to_crm"
                        ],
                        "allowed_connection_ids": [
                          "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
                        ],
                        "monthly_budget_credits": 1000,
                        "per_order_max_credits": 500,
                        "budget": {
                          "monthly_credits": 1000,
                          "spent": 400,
                          "remaining": 600,
                          "resets_at": "2026-10-01T00:00:00Z"
                        },
                        "webhook_url": "https://agent.example.com/mydatahub/events",
                        "disclosure": "account"
                      },
                      "secret": "mdh_test_Example0000000000000000000000000"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/api-keys/{id}": {
      "patch": {
        "operationId": "updateApiKey",
        "summary": "Update an API key",
        "description": "Change a key's label, scopes, allowlist, expiry or, for an agent key, its tools, connections, budget and cap. Only a signed-in person, through OAuth, may: no key changes its own limits, and an agent key never takes admin.",
        "tags": [
          "Keys"
        ],
        "security": [
          {
            "OAuth2": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an API key id: key_ followed by a 26 character ULID in upper case Crockford base32, such as key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyUpdate"
              },
              "examples": {
                "illustrative": {
                  "summary": "Raise an agent key budget",
                  "value": {
                    "monthly_budget_credits": 2000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated key.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Raise an agent key budget",
                    "value": {
                      "id": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3",
                      "kind": "agent",
                      "label": "SDR agent",
                      "mode": "live",
                      "prefix": "mdh_live_7Kq2",
                      "scopes": [
                        "counts:read",
                        "quotes:read",
                        "orders:write",
                        "orders:read",
                        "records:read",
                        "pushes:write"
                      ],
                      "ip_allowlist": [],
                      "created_at": "2026-09-20T09:00:00Z",
                      "created_by": "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8",
                      "last_used_at": "2026-09-26T02:00:00Z",
                      "expires_at": "2027-03-31T00:00:00Z",
                      "revoked_at": null,
                      "allowed_tools": [
                        "count_audience",
                        "quote_order",
                        "create_order",
                        "fetch_order_records",
                        "push_to_crm"
                      ],
                      "allowed_connection_ids": [
                        "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
                      ],
                      "monthly_budget_credits": 2000,
                      "per_order_max_credits": 500,
                      "budget": {
                        "monthly_credits": 2000,
                        "spent": 400,
                        "remaining": 1600,
                        "resets_at": "2026-10-01T00:00:00Z"
                      },
                      "webhook_url": "https://agent.example.com/mydatahub/events",
                      "disclosure": "account"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      },
      "delete": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Revoke a key at once. Orders it placed stay in the audit trail. A signed-in person revokes keys through OAuth.",
        "tags": [
          "Keys"
        ],
        "security": [
          {
            "OAuth2": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an API key id: key_ followed by a 26 character ULID in upper case Crockford base32, such as key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "key_01JB3Z9R6T1Y5W8ZAK8Q2V7XN3"
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/connections": {
      "get": {
        "operationId": "listConnections",
        "summary": "List CRM connections",
        "description": "CRM and destination connections with their status.",
        "tags": [
          "CRM push"
        ],
        "security": [
          {
            "OAuth2": [
              "pushes:write"
            ]
          },
          {
            "ApiKey": [
              "pushes:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of connections.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "One HubSpot connection",
                    "value": {
                      "data": [
                        {
                          "id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G",
                          "provider": "hubspot",
                          "name": "Sales HubSpot",
                          "status": "connected",
                          "authorise_url": null,
                          "read_only_overlap": true,
                          "created_at": "2026-09-20T09:30:00Z",
                          "last_used_at": "2026-09-26T02:05:00Z"
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      },
      "post": {
        "operationId": "createConnection",
        "summary": "Create a CRM connection",
        "description": "Start a connection to HubSpot, Salesforce, Google Sheets, Deliverite, a webhook or CSV. OAuth providers return an authorise_url for a person to approve in the app.",
        "tags": [
          "CRM push"
        ],
        "security": [
          {
            "OAuth2": [
              "pushes:write"
            ]
          },
          {
            "ApiKey": [
              "pushes:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectionRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Connect HubSpot",
                  "value": {
                    "provider": "hubspot",
                    "name": "Sales HubSpot"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The connection.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Connection"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Connect HubSpot",
                    "value": {
                      "id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G",
                      "provider": "hubspot",
                      "name": "Sales HubSpot",
                      "status": "pending_authorisation",
                      "authorise_url": "https://mydatahub.emailmovers.com/connections/conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G/authorise",
                      "read_only_overlap": true,
                      "created_at": "2026-09-20T09:30:00Z",
                      "last_used_at": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/connections/{id}/overlap": {
      "post": {
        "operationId": "checkConnectionOverlap",
        "summary": "Check CRM overlap",
        "description": "The New to you check before an order: read-only, email-only, salted SHA-256 matching in memory, nothing retained and nothing added to our database. Matched records are never charged.",
        "tags": [
          "CRM push"
        ],
        "security": [
          {
            "OAuth2": [
              "pushes:write"
            ]
          },
          {
            "ApiKey": [
              "pushes:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
            "schema": {
              "type": "string",
              "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
              ]
            },
            "example": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OverlapRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Overlap with HubSpot",
                  "value": {
                    "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The overlap.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Overlap"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Overlap with HubSpot",
                    "value": {
                      "connection_id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G",
                      "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                      "records": 4650,
                      "already_held": 548,
                      "new_to_you": 4102,
                      "method": "salted_sha256_in_memory",
                      "retained": false,
                      "checked_at": "2026-09-26T10:12:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/orders/{id}/pushes": {
      "post": {
        "operationId": "createPush",
        "summary": "Push an order to a CRM",
        "description": "Push an order's records to a connection, keyed on mydatahub_record_id with the MyDataHub property group. dry_run defaults to true and reports what would change. A live push needs approval: a person's confirmation_token (or MCP elicitation), or an agent key whose allowed_tools include push_to_crm and whose allowed_connection_ids include the connection; otherwise 403 confirmation-required. Records only: nothing is ever sent to the contacts. Free.",
        "tags": [
          "CRM push"
        ],
        "security": [
          {
            "OAuth2": [
              "pushes:write"
            ]
          },
          {
            "ApiKey": [
              "pushes:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "schema": {
              "type": "string",
              "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
              ]
            },
            "example": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Dry run to HubSpot",
                  "value": {
                    "connection_id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The push, or its dry run.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Push"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Dry run to HubSpot",
                    "value": {
                      "id": "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5",
                      "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "connection_id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G",
                      "dry_run": true,
                      "status": "completed",
                      "summary": {
                        "to_create": 4102,
                        "to_update": 0,
                        "already_present": 0,
                        "skipped": 0,
                        "failed": 0
                      },
                      "property_group": [
                        "mydatahub_record_id",
                        "licence_expires_at",
                        "lawful_basis",
                        "article14_status",
                        "tps_ctps_screened_at",
                        "subscriber_class",
                        "suppression_status",
                        "compliance_receipt_url"
                      ],
                      "sample": {
                        "mydatahub_record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                        "licence_expires_at": "2027-09-26",
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "article14_status": "notified",
                        "tps_ctps_screened_at": "2026-09-12",
                        "subscriber_class": "ltd",
                        "suppression_status": "none",
                        "compliance_receipt_url": "https://mydatahub.emailmovers.com/receipts/rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R"
                      },
                      "errors": [],
                      "created_at": "2026-09-26T10:20:00Z",
                      "completed_at": "2026-09-26T10:20:03Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional",
        "x-mcp-tool": "push_to_crm"
      }
    },
    "/pushes/{id}": {
      "get": {
        "operationId": "getPush",
        "summary": "Get a push",
        "description": "A push's status and summary: to create, to update, already present, skipped and failed.",
        "tags": [
          "CRM push"
        ],
        "security": [
          {
            "OAuth2": [
              "orders:read"
            ]
          },
          {
            "ApiKey": [
              "orders:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a CRM push id: psh_ followed by a 26 character ULID in upper case Crockford base32, such as psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5.",
            "schema": {
              "type": "string",
              "pattern": "^psh_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5"
              ]
            },
            "example": "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5"
          }
        ],
        "responses": {
          "200": {
            "description": "The push.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Push"
                },
                "examples": {
                  "illustrative": {
                    "summary": "A finished dry run",
                    "value": {
                      "id": "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5",
                      "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "connection_id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G",
                      "dry_run": true,
                      "status": "completed",
                      "summary": {
                        "to_create": 4102,
                        "to_update": 0,
                        "already_present": 0,
                        "skipped": 0,
                        "failed": 0
                      },
                      "property_group": [
                        "mydatahub_record_id",
                        "licence_expires_at",
                        "lawful_basis",
                        "article14_status",
                        "tps_ctps_screened_at",
                        "subscriber_class",
                        "suppression_status",
                        "compliance_receipt_url"
                      ],
                      "sample": {
                        "mydatahub_record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                        "licence_expires_at": "2027-09-26",
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "article14_status": "notified",
                        "tps_ctps_screened_at": "2026-09-12",
                        "subscriber_class": "ltd",
                        "suppression_status": "none",
                        "compliance_receipt_url": "https://mydatahub.emailmovers.com/receipts/rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R"
                      },
                      "errors": [],
                      "created_at": "2026-09-26T10:20:00Z",
                      "completed_at": "2026-09-26T10:20:03Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/pushes/{id}/retry": {
      "post": {
        "operationId": "retryPush",
        "summary": "Retry a push",
        "description": "Retry the failed records of a partial or failed push. A live retry needs the same approval as the push it retries.",
        "tags": [
          "CRM push"
        ],
        "security": [
          {
            "OAuth2": [
              "pushes:write"
            ]
          },
          {
            "ApiKey": [
              "pushes:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a CRM push id: psh_ followed by a 26 character ULID in upper case Crockford base32, such as psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5.",
            "schema": {
              "type": "string",
              "pattern": "^psh_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5"
              ]
            },
            "example": "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5"
          }
        ],
        "responses": {
          "202": {
            "description": "The push, queued again.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Push"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Retry a partial push",
                    "value": {
                      "id": "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5",
                      "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "connection_id": "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G",
                      "dry_run": false,
                      "status": "queued",
                      "summary": {
                        "to_create": 4102,
                        "to_update": 0,
                        "already_present": 0,
                        "skipped": 0,
                        "failed": 0
                      },
                      "property_group": [
                        "mydatahub_record_id",
                        "licence_expires_at",
                        "lawful_basis",
                        "article14_status",
                        "tps_ctps_screened_at",
                        "subscriber_class",
                        "suppression_status",
                        "compliance_receipt_url"
                      ],
                      "sample": {
                        "mydatahub_record_id": "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8",
                        "licence_expires_at": "2027-09-26",
                        "lawful_basis": "legitimate_interests_art6_1_f",
                        "article14_status": "notified",
                        "tps_ctps_screened_at": "2026-09-12",
                        "subscriber_class": "ltd",
                        "suppression_status": "none",
                        "compliance_receipt_url": "https://mydatahub.emailmovers.com/receipts/rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R"
                      },
                      "errors": [],
                      "created_at": "2026-09-26T10:20:00Z",
                      "completed_at": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "summary": "List webhook endpoints",
        "description": "Webhook endpoints, their events and pinned MyDataHub-Version.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "OAuth2": [
              "webhooks:write"
            ]
          },
          {
            "ApiKey": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of endpoints.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "One endpoint",
                    "value": {
                      "data": [
                        {
                          "id": "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA",
                          "url": "https://agent.example.com/mydatahub/events",
                          "events": [
                            "order.ready",
                            "credits.low",
                            "suppression.created"
                          ],
                          "api_version": "2027-01-15",
                          "status": "active",
                          "description": "SDR agent",
                          "created_at": "2026-09-20T09:45:00Z"
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "summary": "Create a webhook endpoint",
        "description": "Register an https endpoint for events. Deliveries follow Standard Webhooks (webhook-id, webhook-timestamp, webhook-signature; HMAC-SHA256 with a whsec_ secret, shown once) and retry over 24 hours. The endpoint is pinned to the request's MyDataHub-Version.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "OAuth2": [
              "webhooks:write"
            ]
          },
          {
            "ApiKey": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointRequest"
              },
              "examples": {
                "illustrative": {
                  "summary": "Order and credit events",
                  "value": {
                    "url": "https://agent.example.com/mydatahub/events",
                    "events": [
                      "order.ready",
                      "credits.low",
                      "suppression.created"
                    ],
                    "description": "SDR agent"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The endpoint and its secret.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointCreated"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Order and credit events",
                    "value": {
                      "endpoint": {
                        "id": "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA",
                        "url": "https://agent.example.com/mydatahub/events",
                        "events": [
                          "order.ready",
                          "credits.low",
                          "suppression.created"
                        ],
                        "api_version": "2027-01-15",
                        "status": "active",
                        "description": "SDR agent",
                        "created_at": "2026-09-20T09:45:00Z"
                      },
                      "secret": "whsec_ExampleSecret0000000000000000000"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false,
        "x-idempotency-key": "optional"
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "summary": "Delete a webhook endpoint",
        "description": "Stop deliveries to an endpoint. Its events stay in the event log for 30 days.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "OAuth2": [
              "webhooks:write"
            ]
          },
          {
            "ApiKey": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a webhook endpoint id: whk_ followed by a 26 character ULID in upper case Crockford base32, such as whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^whk_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhookEndpoint",
        "summary": "Send a test event",
        "description": "Send a signed test event to an endpoint and report the response.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "OAuth2": [
              "webhooks:write"
            ]
          },
          {
            "ApiKey": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Format: a webhook endpoint id: whk_ followed by a 26 character ULID in upper case Crockford base32, such as whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA.",
            "schema": {
              "type": "string",
              "pattern": "^whk_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "examples": [
                "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA"
              ]
            },
            "example": "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA"
          }
        ],
        "responses": {
          "200": {
            "description": "The delivery result.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTest"
                },
                "examples": {
                  "illustrative": {
                    "summary": "A delivered test",
                    "value": {
                      "event_id": "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M",
                      "delivered": true,
                      "status_code": 200,
                      "duration_ms": 182
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/events": {
      "get": {
        "operationId": "listEvents",
        "summary": "List events",
        "description": "Replay events from the last 30 days, oldest first, in the same envelope webhooks deliver. Use since to catch up after downtime.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "OAuth2": [
              "webhooks:write"
            ]
          },
          {
            "ApiKey": [
              "webhooks:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Events after this time, up to 30 days back.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-09-26T10:00:00Z"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "order.ready",
                "order.failed",
                "audience.refreshed",
                "credits.low",
                "credits.topped_up",
                "warranty.replacement_issued",
                "suppression.created",
                "push.completed",
                "push.partial",
                "push.failed",
                "connection.expired"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from next_cursor. Pass it back unchanged.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventList"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Events since the order",
                    "value": {
                      "data": [
                        {
                          "id": "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M",
                          "type": "order.ready",
                          "timestamp": "2026-09-26T10:16:04Z",
                          "api_version": "2027-01-15",
                          "data": {
                            "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                            "records": 5000,
                            "records_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/records",
                            "receipt_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/receipt"
                          }
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": false
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiDocument",
        "summary": "Get this OpenAPI document",
        "description": "This document: OpenAPI 3.1 with x-cost-credits and x-free on every operation, generated from the same schemas as the MCP tools.",
        "tags": [
          "Meta"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenApiDocument"
                },
                "examples": {
                  "illustrative": {
                    "summary": "The first lines",
                    "value": {
                      "openapi": "3.1.1",
                      "info": {
                        "title": "MyDataHub API",
                        "version": "2.0.0"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Check health",
        "description": "Whether the API is up, with the release, the latest MyDataHub-Version, the current dataset version and how old its TPS and CTPS screen is.",
        "tags": [
          "Meta"
        ],
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/MyDataHubVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Health.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "examples": {
                  "illustrative": {
                    "summary": "Healthy",
                    "value": {
                      "status": "ok",
                      "version": "2.0.0",
                      "api_version": "2027-01-15",
                      "dataset_version": "2026-W39",
                      "tps_screen": {
                        "screened_at": "2026-09-25",
                        "age_days": 1,
                        "status": "ok"
                      },
                      "time": "2026-09-26T10:14:00Z",
                      "status_page": "https://status.emailmovers.com"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-cost-credits": 0,
        "x-free": true,
        "x-anonymous": true
      }
    }
  },
  "webhooks": {
    "order.ready": {
      "post": {
        "operationId": "webhookOrderReady",
        "summary": "order.ready event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderReadyEvent"
              },
              "examples": {
                "illustrative": {
                  "summary": "An order is ready",
                  "value": {
                    "id": "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M",
                    "type": "order.ready",
                    "timestamp": "2026-09-26T10:16:04Z",
                    "api_version": "2027-01-15",
                    "data": {
                      "order_id": "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E",
                      "records": 5000,
                      "records_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/records",
                      "receipt_url": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E/receipt"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "order.failed": {
      "post": {
        "operationId": "webhookOrderFailed",
        "summary": "order.failed event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderFailedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "audience.refreshed": {
      "post": {
        "operationId": "webhookAudienceRefreshed",
        "summary": "audience.refreshed event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudienceRefreshedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "credits.low": {
      "post": {
        "operationId": "webhookCreditsLow",
        "summary": "credits.low event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreditsLowEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "credits.topped_up": {
      "post": {
        "operationId": "webhookCreditsToppedUp",
        "summary": "credits.topped_up event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreditsToppedUpEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "warranty.replacement_issued": {
      "post": {
        "operationId": "webhookWarrantyReplacementIssued",
        "summary": "warranty.replacement_issued event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WarrantyReplacementEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "suppression.created": {
      "post": {
        "operationId": "webhookSuppressionCreated",
        "summary": "suppression.created event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuppressionCreatedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "push.completed": {
      "post": {
        "operationId": "webhookPushCompleted",
        "summary": "push.completed event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushCompletedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "push.partial": {
      "post": {
        "operationId": "webhookPushPartial",
        "summary": "push.partial event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushPartialEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "push.failed": {
      "post": {
        "operationId": "webhookPushFailed",
        "summary": "push.failed event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushFailedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    },
    "connection.expired": {
      "post": {
        "operationId": "webhookConnectionExpired",
        "summary": "connection.expired event",
        "description": "Delivered to your endpoint under Standard Webhooks: verify webhook-signature (HMAC-SHA256 over webhook-id, webhook-timestamp and the body with your whsec_ secret) and treat webhook-id as the idempotency key. Any 2xx acknowledges; anything else is retried over 24 hours with backoff.",
        "tags": [
          "Webhooks"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The event id; your idempotency key."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds when the delivery was signed."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One or more space separated v1,base64 signatures."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectionExpiredEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged."
          },
          "400": {
            "description": "Not acknowledged; the delivery is retried with backoff."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Account": {
        "type": "object",
        "properties": {
          "organisation": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^org_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: an organisation id: org_ followed by a 26 character ULID in upper case Crockford base32, such as org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8.",
                "examples": [
                  "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8"
                ]
              },
              "name": {
                "type": "string"
              },
              "business_details": {
                "$ref": "#/components/schemas/BusinessDetails"
              }
            },
            "required": [
              "id",
              "name",
              "business_details"
            ]
          },
          "user": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                    "description": "Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8.",
                    "examples": [
                      "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
                    ]
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "name"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The signed-in person; null when the caller is an API key."
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "live keys (mdh_live_) spend real credits; test keys (mdh_test_) return synthetic data and never charge."
          },
          "plan": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
              },
              "name": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "free",
                  "subscription",
                  "pack"
                ]
              },
              "renews_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "cancel_at_period_end": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "kind",
              "renews_at",
              "cancel_at_period_end"
            ]
          },
          "balance": {
            "type": "object",
            "properties": {
              "credits": {
                "type": "number",
                "description": "Credits available to spend now."
              },
              "pack_credits": {
                "type": "number",
                "description": "From credit packs: never expire."
              },
              "subscription_credits": {
                "type": "number",
                "description": "From the plan: roll over while subscribed, up to the cap."
              },
              "rollover_cap": {
                "anyOf": [
                  {
                    "type": "integer",
                    "minimum": 0
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "low_threshold": {
                "anyOf": [
                  {
                    "type": "integer",
                    "minimum": 0
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The credits.low webhook fires when the balance crosses this."
              }
            },
            "required": [
              "credits",
              "pack_credits",
              "subscription_credits",
              "rollover_cap",
              "low_threshold"
            ],
            "description": "Credits by source."
          },
          "prices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditRule"
            },
            "description": "What each action costs in credits."
          },
          "gbp_per_credit": {
            "type": "number",
            "minimum": 0,
            "description": "Your plan's price per credit, excluding VAT."
          },
          "rate_limit": {
            "$ref": "#/components/schemas/RateLimit"
          },
          "key": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                    "description": "Format: an API key id: key_ followed by a 26 character ULID in upper case Crockford base32, such as key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA.",
                    "examples": [
                      "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
                    ]
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "standard",
                      "agent"
                    ]
                  },
                  "budget": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Budget"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "per_order_max_credits": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 0
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "expires_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "id",
                  "kind",
                  "budget",
                  "per_order_max_credits",
                  "expires_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The calling key and, for an agent key, its budget; null for a person."
          },
          "account_manager": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "calendar_url": {
                    "type": "string",
                    "format": "uri"
                  }
                },
                "required": [
                  "name",
                  "calendar_url"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The named person behind Talk to us."
          },
          "agreements": {
            "type": "object",
            "properties": {
              "dlsa": {
                "$ref": "#/components/schemas/Agreement"
              },
              "dpa": {
                "$ref": "#/components/schemas/Agreement"
              }
            },
            "required": [
              "dlsa",
              "dpa"
            ],
            "description": "The Data Licence and Sharing Agreement (accepted with every order, or with an agent key that orders on its own) and the Article 28 DPA (accepted with the first suppression list)."
          }
        },
        "required": [
          "organisation",
          "user",
          "mode",
          "plan",
          "balance",
          "prices",
          "gbp_per_credit",
          "rate_limit",
          "key",
          "account_manager",
          "agreements"
        ],
        "description": "Balance, plan, per-action prices, rate limit and the calling key's budget."
      },
      "AccountAgreementsRequest": {
        "type": "object",
        "properties": {
          "dpa_accepted_version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "The version of the Article 28 data processing agreement the owner accepts: the version in force, the account's agreements.dpa.version."
          }
        },
        "required": [
          "dpa_accepted_version"
        ],
        "additionalProperties": false,
        "description": "An owner's acceptance of the Article 28 data processing agreement, which a suppression upload needs first."
      },
      "AccountCancellation": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
          },
          "cancel_at_period_end": {
            "type": "boolean",
            "const": true
          },
          "ends_at": {
            "type": "string",
            "format": "date"
          },
          "pack_credits_kept": {
            "type": "number",
            "description": "Credit pack credits never expire and survive cancellation."
          },
          "subscription_credits_usable_until": {
            "type": "string",
            "format": "date"
          },
          "licences_unaffected": {
            "type": "boolean",
            "const": true,
            "description": "Delivered records stay licensed to the end of their term."
          }
        },
        "required": [
          "plan",
          "cancel_at_period_end",
          "ends_at",
          "pack_credits_kept",
          "subscription_credits_usable_until",
          "licences_unaffected"
        ],
        "description": "The plan ends at the end of its period; credits and licences survive to the end of their term."
      },
      "AccountCancellationRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "description": "Optional; never required.",
            "type": "string",
            "maxLength": 1000
          }
        },
        "additionalProperties": false,
        "description": "Cancel the rolling plan at period end."
      },
      "AccountUpdateRequest": {
        "type": "object",
        "properties": {
          "business_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^\\P{Cc}*$",
            "description": "The organisation's business name, 1 to 200 characters, with no control character such as a line break."
          },
          "uk_business": {
            "type": "boolean",
            "const": true,
            "description": "true confirms that the organisation is a UK business."
          }
        },
        "required": [
          "business_name",
          "uk_business"
        ],
        "additionalProperties": false,
        "description": "The business name and a UK business confirmation, which a self-serve account needs before its first order. Only an organisation made by self-serve sign-up takes it."
      },
      "AccountUsage": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "credits_charged": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "credits_refunded": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "credits_added": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "by_action": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "action": {
                  "type": "string",
                  "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
                },
                "calls": {
                  "type": "integer",
                  "minimum": 0
                },
                "credits": {
                  "type": "number",
                  "minimum": 0,
                  "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
                }
              },
              "required": [
                "action",
                "calls",
                "credits"
              ]
            }
          },
          "by_key": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key_id": {
                  "type": "string",
                  "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                  "description": "Format: an API key id: key_ followed by a 26 character ULID in upper case Crockford base32, such as key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA.",
                  "examples": [
                    "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
                  ]
                },
                "label": {
                  "type": "string"
                },
                "credits": {
                  "type": "number",
                  "minimum": 0,
                  "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
                }
              },
              "required": [
                "key_id",
                "label",
                "credits"
              ]
            }
          }
        },
        "required": [
          "from",
          "to",
          "credits_charged",
          "credits_refunded",
          "credits_added",
          "by_action",
          "by_key"
        ],
        "description": "Credits charged, refunded and added in a period, by action and by key."
      },
      "ActionPathStep": {
        "type": "object",
        "properties": {
          "step": {
            "type": "integer",
            "minimum": 1
          },
          "action": {
            "type": "string",
            "description": "An MCP tool, a REST operation or a URL."
          },
          "rest": {
            "description": "The REST operation, such as POST /v1/quotes.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "step",
          "action",
          "rest",
          "description"
        ],
        "description": "One step from a price to a delivered order."
      },
      "AgentBudgetProblem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI under https://emailmovers.com/mydatahub/docs/errors/ naming the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short summary of the problem type."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "description": "What happened on this request, in plain English."
          },
          "instance": {
            "description": "The request path or a request id this problem belongs to.",
            "type": "string"
          },
          "code": {
            "type": "string",
            "const": "agent-budget-exceeded"
          },
          "next_step": {
            "type": "string",
            "description": "What to do next, in plain English."
          },
          "did_you_mean": {
            "description": "The closest valid values, best first.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "description": "For validation-failed: every problem found, each with a JSON pointer.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProblemError"
            }
          },
          "required_scope": {
            "description": "For insufficient-scope: the scope to request, such as orders:write.",
            "type": "string"
          },
          "retry_after_seconds": {
            "description": "For rate-limited and service-unavailable: the same value as the Retry-After header.",
            "type": "integer",
            "minimum": 0
          },
          "budget": {
            "$ref": "#/components/schemas/Budget"
          },
          "per_order_max_credits": {
            "type": "integer",
            "minimum": 0
          },
          "quote_id": {
            "description": "The machine quote the key could not settle; absent for an enrichment.",
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "credits_required": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "approval_url": {
            "type": "string",
            "format": "uri",
            "description": "Where the key owner approves this spend in the app."
          },
          "top_up_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "next_step",
          "budget",
          "approval_url",
          "top_up_url"
        ],
        "description": "403: the agent key's per-order cap or monthly budget does not cover the machine quote or the enrichment. No order was created. The owner gets a signed notice only when an endpoint is registered at the key's webhook_url."
      },
      "AgentKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an API key id: key_ followed by a 26 character ULID in upper case Crockford base32, such as key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "label": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "live keys (mdh_live_) spend real credits; test keys (mdh_test_) return synthetic data and never charge."
          },
          "prefix": {
            "type": "string",
            "description": "The first characters of the secret, such as mdh_live_7Kq2."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "account:read",
                "counts:read",
                "previews:read",
                "audiences:read",
                "audiences:write",
                "quotes:read",
                "orders:read",
                "orders:write",
                "records:read",
                "enrich:write",
                "suppressions:read",
                "suppressions:write",
                "pushes:write",
                "webhooks:write",
                "samples:request",
                "admin"
              ]
            }
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$"
                },
                {
                  "type": "string",
                  "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$"
                }
              ],
              "description": "An IPv4 or IPv6 range in CIDR notation, such as 203.0.113.0/24."
            },
            "description": "CIDR ranges the key may be used from; empty allows any address."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string",
            "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8.",
            "examples": [
              "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "revoked_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "type": "string",
            "const": "agent"
          },
          "allowed_tools": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "get_plans",
                "get_account",
                "list_filters",
                "search_filter_values",
                "expand_job_titles",
                "resolve_location",
                "compile_audience",
                "count_audience",
                "preview_records",
                "save_audience",
                "list_audiences",
                "list_field_sets",
                "quote_order",
                "create_order",
                "get_order",
                "fetch_order_records",
                "push_to_crm",
                "lookup_company",
                "enrich_contact",
                "check_suppression",
                "report_objection",
                "get_compliance_receipt"
              ]
            },
            "description": "The tools the key may call; a spending tool (create_order, enrich_contact) only if listed."
          },
          "allowed_connection_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
              "examples": [
                "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
              ]
            },
            "description": "The CRM connections push_to_crm may push to live; empty allows dry runs only."
          },
          "monthly_budget_credits": {
            "type": "integer",
            "minimum": 0
          },
          "per_order_max_credits": {
            "type": "integer",
            "minimum": 0
          },
          "budget": {
            "description": "The live spend meter.",
            "$ref": "#/components/schemas/Budget"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          },
          "disclosure": {
            "type": "string",
            "enum": [
              "account",
              "anonymous"
            ],
            "description": "account: counts as the organisation's own; anonymous: every anonymous visitor's rule, for a public assistant."
          }
        },
        "required": [
          "id",
          "label",
          "mode",
          "prefix",
          "scopes",
          "ip_allowlist",
          "created_at",
          "created_by",
          "last_used_at",
          "expires_at",
          "revoked_at",
          "kind",
          "allowed_tools",
          "allowed_connection_ids",
          "monthly_budget_credits",
          "per_order_max_credits",
          "budget",
          "webhook_url",
          "disclosure"
        ],
        "description": "An API key with kind agent: it spends without a human step only when the tool is in allowed_tools, per_order_max_credits covers the machine quote and monthly budget remains. Only a person in the app changes these limits, never a key."
      },
      "Agreement": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string",
            "description": "The version in force: draft until the text is approved."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "accepted": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "string"
                  },
                  "accepted_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "accepted_by": {
                    "type": "string",
                    "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                    "description": "Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8.",
                    "examples": [
                      "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
                    ]
                  }
                },
                "required": [
                  "version",
                  "accepted_at",
                  "accepted_by"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The organisation's acceptance of the latest version it accepted: which version, when and by whom, first time for that version. null until one is accepted. When version (the one in force) differs, the agreement is accepted again."
          }
        },
        "required": [
          "name",
          "version",
          "url",
          "accepted"
        ]
      },
      "AllGroup": {
        "type": "object",
        "properties": {
          "all": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WhereNode"
            }
          }
        },
        "required": [
          "all"
        ],
        "additionalProperties": false,
        "description": "AND: every node inside must match."
      },
      "AnyGroup": {
        "type": "object",
        "properties": {
          "any": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WhereNode"
            }
          }
        },
        "required": [
          "any"
        ],
        "additionalProperties": false,
        "description": "OR: at least one node inside must match."
      },
      "ApiKey": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/StandardApiKey"
          },
          {
            "$ref": "#/components/schemas/AgentKey"
          }
        ],
        "description": "A standard API key or an agent key. The secret is never shown again.",
        "discriminator": {
          "propertyName": "kind",
          "mapping": {
            "standard": "#/components/schemas/StandardApiKey",
            "agent": "#/components/schemas/AgentKey"
          }
        }
      },
      "ApiKeyCreated": {
        "type": "object",
        "properties": {
          "key": {
            "$ref": "#/components/schemas/ApiKey"
          },
          "secret": {
            "type": "string",
            "pattern": "^mdh_(live|test)_[0-9A-Za-z]{32}$",
            "description": "The secret, shown once. Send it as Authorization: Bearer."
          }
        },
        "required": [
          "key",
          "secret"
        ],
        "description": "A new key and its secret, shown once."
      },
      "ApiKeyList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKey"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of API keys, newest first."
      },
      "ApiKeyRequest": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "standard",
              "agent"
            ]
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "mode": {
            "default": "live",
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "live keys (mdh_live_) spend real credits; test keys (mdh_test_) return synthetic data and never charge."
          },
          "scopes": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "account:read",
                "counts:read",
                "previews:read",
                "audiences:read",
                "audiences:write",
                "quotes:read",
                "orders:read",
                "orders:write",
                "records:read",
                "enrich:write",
                "suppressions:read",
                "suppressions:write",
                "pushes:write",
                "webhooks:write",
                "samples:request",
                "admin"
              ]
            },
            "description": "The key's scopes. An agent key never takes admin, and no key takes account:write, which only a signed-in owner uses."
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$"
                },
                {
                  "type": "string",
                  "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$"
                }
              ],
              "description": "An IPv4 or IPv6 range in CIDR notation, such as 203.0.113.0/24."
            },
            "description": "CIDR ranges the key may be used from; empty allows any address."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 date and time, with Z or an offset such as +01:00."
          },
          "allowed_tools": {
            "description": "Agent keys only, and required there: the tools the key may call.",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "get_plans",
                "get_account",
                "list_filters",
                "search_filter_values",
                "expand_job_titles",
                "resolve_location",
                "compile_audience",
                "count_audience",
                "preview_records",
                "save_audience",
                "list_audiences",
                "list_field_sets",
                "quote_order",
                "create_order",
                "get_order",
                "fetch_order_records",
                "push_to_crm",
                "lookup_company",
                "enrich_contact",
                "check_suppression",
                "report_objection",
                "get_compliance_receipt"
              ]
            }
          },
          "allowed_connection_ids": {
            "description": "Agent keys only: the connections push_to_crm may push to live. Default none.",
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
              "examples": [
                "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
              ]
            }
          },
          "monthly_budget_credits": {
            "description": "Agent keys only. Default 1000 credits a month (to confirm).",
            "type": "integer",
            "minimum": 0
          },
          "per_order_max_credits": {
            "description": "Agent keys only, and required there: the most one order may spend, no more than monthly_budget_credits.",
            "type": "integer",
            "minimum": 0
          },
          "webhook_url": {
            "description": "Agent keys only: the https endpoint its events go to.",
            "type": "string",
            "format": "uri",
            "pattern": "^https://"
          },
          "disclosure": {
            "description": "Agent keys only. anonymous makes every count follow an anonymous visitor's rules, for a public assistant. Default account.",
            "type": "string",
            "enum": [
              "account",
              "anonymous"
            ]
          },
          "licence_accepted_version": {
            "description": "Agent keys only, and required for one that spends on its own (create_order or enrich_contact, with a monthly budget and a per-order cap above 0): the version of the Data Licence and Sharing Agreement the person making the key accepts, the account's agreements.dlsa.version. Every order and enrichment the key makes on its own carries that acceptance. A key with a budget or cap of 0 needs none: a person approves, and accepts, each of its spends.",
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "kind",
          "label",
          "scopes"
        ],
        "additionalProperties": false,
        "description": "A new key, made by a signed-in person (an OAuth user token with admin), never by a key. An agent key needs allowed_tools and per_order_max_credits, no more than its monthly budget, and never takes admin.",
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "kind": {
                  "const": "agent"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "allowed_tools": true,
                "per_order_max_credits": true,
                "scopes": {
                  "type": "array",
                  "not": {
                    "contains": {
                      "const": "admin"
                    }
                  }
                }
              },
              "required": [
                "allowed_tools",
                "per_order_max_credits"
              ]
            },
            "else": {
              "type": "object",
              "properties": {
                "allowed_tools": false,
                "allowed_connection_ids": false,
                "monthly_budget_credits": false,
                "per_order_max_credits": false,
                "webhook_url": false,
                "disclosure": false
              }
            }
          }
        ]
      },
      "ApiKeyUpdate": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "scopes": {
            "description": "Replacement scopes. An agent key never takes admin, and no key takes account:write, which only a signed-in owner uses.",
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "account:read",
                "counts:read",
                "previews:read",
                "audiences:read",
                "audiences:write",
                "quotes:read",
                "orders:read",
                "orders:write",
                "records:read",
                "enrich:write",
                "suppressions:read",
                "suppressions:write",
                "pushes:write",
                "webhooks:write",
                "samples:request",
                "admin"
              ]
            }
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$"
                },
                {
                  "type": "string",
                  "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$"
                }
              ],
              "description": "An IPv4 or IPv6 range in CIDR notation, such as 203.0.113.0/24."
            },
            "description": "CIDR ranges the key may be used from; empty allows any address."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "RFC 3339 date and time, with Z or an offset such as +01:00."
              },
              {
                "type": "null"
              }
            ]
          },
          "allowed_tools": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "get_plans",
                "get_account",
                "list_filters",
                "search_filter_values",
                "expand_job_titles",
                "resolve_location",
                "compile_audience",
                "count_audience",
                "preview_records",
                "save_audience",
                "list_audiences",
                "list_field_sets",
                "quote_order",
                "create_order",
                "get_order",
                "fetch_order_records",
                "push_to_crm",
                "lookup_company",
                "enrich_contact",
                "check_suppression",
                "report_objection",
                "get_compliance_receipt"
              ]
            }
          },
          "allowed_connection_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
              "examples": [
                "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
              ]
            }
          },
          "monthly_budget_credits": {
            "type": "integer",
            "minimum": 0
          },
          "per_order_max_credits": {
            "type": "integer",
            "minimum": 0
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri",
                "pattern": "^https://"
              },
              {
                "type": "null"
              }
            ]
          },
          "disclosure": {
            "type": "string",
            "enum": [
              "account",
              "anonymous"
            ]
          },
          "licence_accepted_version": {
            "description": "The Data Licence and Sharing Agreement version the person changing the key accepts: required when the change lets an agent key spend on its own (create_order or enrich_contact, a budget and a cap above 0), or widens what it spends (a spending tool added, a larger budget or cap), and the key has not accepted the version in force. Sent alone, it renews the key's acceptance.",
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "additionalProperties": false,
        "description": "Members to change on a key, at least one. Only a signed-in person changes a key; a key never changes its own tools, budget or cap.",
        "minProperties": 1
      },
      "Audience": {
        "type": "object",
        "properties": {
          "schema": {
            "type": "string",
            "const": "mydatahub.audience/1",
            "description": "The definition's namespace and version. Older versions are upgraded by a pure function."
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "dataset_version": {
            "description": "The weekly build to count against, such as 2026-W39. Left out, the current version is filled in and returned.",
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "examples": [
              "2026-W39"
            ]
          },
          "where": {
            "description": "The filters. Left out, the audience is the whole dataset after the defaults.",
            "$ref": "#/components/schemas/WhereNode"
          },
          "email_policy": {
            "$ref": "#/components/schemas/EmailPolicy"
          },
          "dedupe": {
            "type": "string",
            "enum": [
              "none",
              "one_per_company",
              "one_per_site"
            ],
            "description": "none keeps every matching contact, one_per_company keeps one contact per company, one_per_site keeps one per site. Default none."
          }
        },
        "required": [
          "schema"
        ],
        "additionalProperties": false,
        "title": "MyDataHub audience definition (mydatahub.audience/1)",
        "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."
      },
      "AudienceCountSummary": {
        "type": "object",
        "properties": {
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "contacts": {
            "type": "integer",
            "minimum": 0
          },
          "companies": {
            "type": "integer",
            "minimum": 0
          },
          "emailable": {
            "type": "integer",
            "minimum": 0
          },
          "counted_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "count_id",
          "dataset_version",
          "contacts",
          "companies",
          "emailable",
          "counted_at"
        ],
        "description": "The headline numbers of one count of an audience."
      },
      "AudienceRef": {
        "anyOf": [
          {
            "type": "string",
            "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "examples": [
              "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
            ]
          },
          {
            "$ref": "#/components/schemas/Audience"
          }
        ],
        "description": "An audience definition (mydatahub.audience/1) inline, or the aud_ id of a saved audience."
      },
      "AudienceRefresh": {
        "type": "object",
        "properties": {
          "audience_id": {
            "type": "string",
            "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "examples": [
              "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
            ]
          },
          "previous": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AudienceCountSummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "current": {
            "$ref": "#/components/schemas/AudienceCountSummary"
          },
          "diff": {
            "type": "object",
            "properties": {
              "contacts": {
                "type": "integer"
              },
              "companies": {
                "type": "integer"
              },
              "emailable": {
                "type": "integer"
              },
              "new_records": {
                "type": "integer",
                "minimum": 0,
                "description": "Records in the audience that were not before."
              },
              "removed_records": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "contacts",
              "companies",
              "emailable",
              "new_records",
              "removed_records"
            ]
          }
        },
        "required": [
          "audience_id",
          "previous",
          "current",
          "diff"
        ],
        "description": "A saved audience recounted on the current dataset version, with the difference."
      },
      "AudienceRefreshedEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "audience.refreshed"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "$ref": "#/components/schemas/AudienceRefresh"
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A saved audience was recounted, with the diff."
      },
      "BetweenFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "company.employee_band",
              "company.turnover_band",
              "company.fleet_band",
              "contact.job_level_rank",
              "email.deliverability_score"
            ]
          },
          "op": {
            "type": "string",
            "const": "between"
          },
          "from": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              {
                "type": "number"
              }
            ],
            "description": "A band code or a number from the field's order."
          },
          "to": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              {
                "type": "number"
              }
            ],
            "description": "A band code or a number from the field's order."
          }
        },
        "required": [
          "field",
          "op",
          "from",
          "to"
        ],
        "additionalProperties": false,
        "description": "The field lies from one value to another inclusive, over the field's order.",
        "examples": [
          {
            "field": "company.employee_band",
            "op": "between",
            "from": "10-19",
            "to": "200-349"
          }
        ],
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.employee_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string",
                  "enum": [
                    "1-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100-199",
                    "200-349",
                    "350-499",
                    "500-999",
                    "1000-1499",
                    "1500-4999",
                    "5000-9999",
                    "10000+"
                  ]
                },
                "to": {
                  "type": "string",
                  "enum": [
                    "1-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100-199",
                    "200-349",
                    "350-499",
                    "500-999",
                    "1000-1499",
                    "1500-4999",
                    "5000-9999",
                    "10000+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.turnover_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string",
                  "enum": [
                    "1-100k",
                    "101k-200k",
                    "201k-500k",
                    "501k-750k",
                    "751k-1M",
                    "1.1M-2M",
                    "2.1M-5M",
                    "5.1M-7.5M",
                    "7.6M-10M",
                    "11M-20M",
                    "21M-50M",
                    "51M-75M",
                    "76M-100M",
                    "100M-250M",
                    "251M-500M",
                    "501M-1B",
                    "1B+"
                  ]
                },
                "to": {
                  "type": "string",
                  "enum": [
                    "1-100k",
                    "101k-200k",
                    "201k-500k",
                    "501k-750k",
                    "751k-1M",
                    "1.1M-2M",
                    "2.1M-5M",
                    "5.1M-7.5M",
                    "7.6M-10M",
                    "11M-20M",
                    "21M-50M",
                    "51M-75M",
                    "76M-100M",
                    "100M-250M",
                    "251M-500M",
                    "501M-1B",
                    "1B+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.fleet_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string",
                  "enum": [
                    "1-2",
                    "3-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100+"
                  ]
                },
                "to": {
                  "type": "string",
                  "enum": [
                    "1-2",
                    "3-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.job_level_rank"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3,
                    4,
                    5,
                    6,
                    7,
                    8,
                    9,
                    10,
                    11,
                    12,
                    13
                  ]
                },
                "to": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3,
                    4,
                    5,
                    6,
                    7,
                    8,
                    9,
                    10,
                    11,
                    12,
                    13
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "email.deliverability_score"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100
                },
                "to": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100
                }
              }
            }
          }
        ]
      },
      "BillingAddress": {
        "type": "object",
        "properties": {
          "line1": {
            "type": [
              "string",
              "null"
            ]
          },
          "line2": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "description": "A county or region, when given.",
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "description": "Two letters, such as GB.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "line1",
          "line2",
          "city",
          "postal_code",
          "state",
          "country"
        ],
        "description": "The billing address Stripe Checkout collected."
      },
      "Breakdown": {
        "type": "object",
        "properties": {
          "by": {
            "type": "string",
            "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"
            ],
            "description": "A field a count can be broken down by."
          },
          "cells": {
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BreakdownCell"
            }
          },
          "other": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OtherBucket"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "by",
          "cells"
        ],
        "description": "A count split by one field: the top 50 cells plus other. Cells under 10 read \"under 10\"."
      },
      "BreakdownCell": {
        "type": "object",
        "properties": {
          "value": {
            "description": "The cell's code as shown, such as director or C. To add the cell to the audience as a filter, use filter_value when present, otherwise value.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "filter_value": {
            "description": "The value a filter takes when it differs from value, such as 6 for director on contact.job_level_rank (filters take ranks).",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "label": {
            "type": "string"
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          },
          "companies": {
            "$ref": "#/components/schemas/CellCount"
          }
        },
        "required": [
          "value",
          "contacts"
        ],
        "description": "One cell of a breakdown."
      },
      "BriefQuestion": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "filter": {
                  "$ref": "#/components/schemas/Filter"
                }
              },
              "required": [
                "label",
                "filter"
              ]
            }
          }
        },
        "required": [
          "id",
          "text",
          "options"
        ],
        "description": "An ambiguity to answer before counting."
      },
      "BriefRequest": {
        "type": "object",
        "properties": {
          "brief": {
            "type": "string",
            "minLength": 3,
            "maxLength": 2000,
            "description": "A plain English brief, such as \"300 finance directors at law firms in Manchester\"."
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          }
        },
        "required": [
          "brief"
        ],
        "additionalProperties": false,
        "description": "A brief to compile into an audience definition."
      },
      "Budget": {
        "type": "object",
        "properties": {
          "monthly_credits": {
            "type": "integer",
            "minimum": 0
          },
          "spent": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "remaining": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "resets_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "monthly_credits",
          "spent",
          "remaining",
          "resets_at"
        ],
        "description": "An agent key's monthly budget in credits."
      },
      "BundleNode": {
        "type": "object",
        "properties": {
          "bundle": {
            "type": "string",
            "enum": [
              "sdm",
              "manager_and_above",
              "owner_managed"
            ]
          }
        },
        "required": [
          "bundle"
        ],
        "additionalProperties": false,
        "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)."
      },
      "BusinessDetails": {
        "type": "object",
        "properties": {
          "confirmed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When a person confirmed the business name and that it is a UK business; null until then."
          },
          "required_before_order": {
            "type": "boolean",
            "description": "true: an order or an enrichment is refused with business-details-required until a person who owns the account confirms them with PATCH /v1/account. Only an organisation made by self-serve sign-up needs them, and whether it does is set when it is made."
          },
          "name_editable": {
            "type": "boolean",
            "description": "true for an organisation made by self-serve sign-up, whose business name PATCH /v1/account sets. false for one Emailmovers set up, which keeps the name staff gave it and needs no business details before an order."
          }
        },
        "required": [
          "confirmed_at",
          "required_before_order",
          "name_editable"
        ],
        "description": "Whether the business name and a UK business confirmation are on record, which a self-serve account needs before its first order."
      },
      "BuyerKit": {
        "type": "object",
        "properties": {
          "draft_lia_url": {
            "type": "string",
            "format": "uri"
          },
          "first_email_wording_url": {
            "type": "string",
            "format": "uri"
          },
          "article30_stub_url": {
            "type": "string",
            "format": "uri"
          },
          "due_diligence_file_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "draft_lia_url",
          "first_email_wording_url",
          "article30_stub_url",
          "due_diligence_file_url"
        ],
        "description": "Four signed documents that help the buyer use the list lawfully."
      },
      "CellCount": {
        "anyOf": [
          {
            "type": "integer",
            "minimum": 0
          },
          {
            "type": "string",
            "const": "under 10"
          },
          {
            "type": "string",
            "const": "suppressed"
          }
        ],
        "description": "A whole number; \"under 10\" when disclosure control withholds a small cell; or \"suppressed\" when secondary suppression hides a cell of 10 or more in a cross-tab or breakdown, so totals cannot be differenced. Anonymous and trial callers see cells rounded to the nearest 5.",
        "examples": [
          4120,
          "under 10",
          "suppressed"
        ]
      },
      "Chip": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "What the chip reads, such as Within 20 miles of Leeds."
          },
          "pointer": {
            "type": "string",
            "description": "JSON pointer to the filter inside audience."
          },
          "from_brief": {
            "type": "string",
            "description": "The words of the brief it came from."
          }
        },
        "required": [
          "label",
          "pointer",
          "from_brief"
        ],
        "description": "One visible, editable filter compiled from the brief."
      },
      "CompanyCompliance": {
        "type": "object",
        "properties": {
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ]
          },
          "subscriber_class": {
            "type": "string",
            "enum": [
              "ltd",
              "plc",
              "llp",
              "scottish_partnership",
              "public_body",
              "charity_incorporated",
              "sole_trader",
              "ordinary_partnership",
              "unknown"
            ]
          },
          "corporate_subscriber": {
            "type": "boolean"
          },
          "email_marketing_basis": {
            "type": "string",
            "enum": [
              "pecr_corporate_subscriber",
              "consent_required"
            ]
          },
          "subscriber_evidence": {
            "type": "object",
            "properties": {
              "companies_house_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "company_type": {
                "type": "string"
              }
            },
            "required": [
              "companies_house_number",
              "company_type"
            ]
          },
          "provenance": {
            "type": "object",
            "properties": {
              "company": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "emailmovers_research",
                      "companies_house",
                      "onspd",
                      "ukbizdirectory",
                      "partner_rampedup"
                    ]
                  },
                  "as_of": {
                    "type": "string",
                    "format": "date"
                  }
                },
                "required": [
                  "source",
                  "as_of"
                ]
              }
            },
            "required": [
              "company"
            ]
          },
          "attribution": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "lawful_basis",
          "subscriber_class",
          "corporate_subscriber",
          "email_marketing_basis",
          "subscriber_evidence",
          "provenance",
          "attribution"
        ],
        "description": "The company facts of the compliance object, for results with no contact."
      },
      "CompanyLookup": {
        "type": "object",
        "properties": {
          "match_confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "company": {
            "type": "object",
            "properties": {
              "companies_house_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "subscriber_class": {
                "type": "string",
                "enum": [
                  "ltd",
                  "plc",
                  "llp",
                  "scottish_partnership",
                  "public_body",
                  "charity_incorporated",
                  "sole_trader",
                  "ordinary_partnership",
                  "unknown"
                ]
              },
              "incorporation_date": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sic_2007": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SicCode"
                }
              },
              "employee_band": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "turnover_band": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "website_domain": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "registered_office": {
                "type": "object",
                "properties": {
                  "town": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "postcode": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "town",
                  "postcode"
                ]
              }
            },
            "required": [
              "companies_house_number",
              "name",
              "status",
              "type",
              "subscriber_class",
              "incorporation_date",
              "sic_2007",
              "employee_band",
              "turnover_band",
              "website_domain",
              "registered_office"
            ]
          },
          "contacts_held": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CellCount"
              },
              {
                "type": "null"
              }
            ],
            "description": "Contacts we hold at the company: a single-company count, so signed-in callers only (null otherwise) and logged. Trial callers see it rounded."
          },
          "contacts_by_level": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/LevelCount"
                }
              },
              {
                "type": "null"
              }
            ],
            "description": "The same count by job level, most senior first, with Level not known last; null when signed out."
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          },
          "compliance": {
            "$ref": "#/components/schemas/CompanyCompliance"
          },
          "credits_charged": {
            "type": "number",
            "const": 0
          }
        },
        "required": [
          "match_confidence",
          "dataset_version",
          "company",
          "contacts_held",
          "contacts_by_level",
          "disclosure",
          "compliance",
          "credits_charged"
        ],
        "description": "Companies House fields for one company and, for signed-in callers, the contacts held there. No contact details."
      },
      "CompanyLookupRequest": {
        "type": "object",
        "properties": {
          "company_number": {
            "type": "string",
            "pattern": "^[A-Z0-9]{8}$",
            "description": "Eight characters in upper case, such as 05046417 or SC123456."
          },
          "domain": {
            "type": "string",
            "minLength": 3,
            "maxLength": 253
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 200
          },
          "town": {
            "description": "Narrows a name search.",
            "type": "string",
            "maxLength": 100
          }
        },
        "additionalProperties": false,
        "description": "A company by exactly one of number, domain or name.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "company_number": true
            },
            "required": [
              "company_number"
            ]
          },
          {
            "type": "object",
            "properties": {
              "domain": true
            },
            "required": [
              "domain"
            ]
          },
          {
            "type": "object",
            "properties": {
              "name": true
            },
            "required": [
              "name"
            ]
          }
        ]
      },
      "CompiledBrief": {
        "type": "object",
        "properties": {
          "audience": {
            "$ref": "#/components/schemas/Audience"
          },
          "readback": {
            "type": "string",
            "description": "The audience in one sentence, to confirm with the person."
          },
          "chips": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Chip"
            }
          },
          "questions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BriefQuestion"
            }
          },
          "unrecognised": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Words of the brief that matched no filter, shown rather than guessed."
          },
          "quantity": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "A quantity named in the brief, such as 300, for quote_order limit."
          }
        },
        "required": [
          "audience",
          "readback",
          "chips",
          "questions",
          "unrecognised",
          "quantity"
        ],
        "description": "An audience definition from a brief, with its chips and any questions."
      },
      "CompiledPlan": {
        "type": "object",
        "properties": {
          "engine_rules_version": {
            "type": "string"
          },
          "defaults_applied": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
            },
            "description": "Defaults the server filled, such as active_companies and named_emails."
          },
          "expanded_terms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpandedTerm"
            }
          },
          "centres": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResolvedCentre"
            }
          },
          "sic_codes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "SIC codes behind any business class filter."
          },
          "geography_sets": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "suppressions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuppressionChecksum"
            }
          }
        },
        "required": [
          "engine_rules_version",
          "defaults_applied",
          "expanded_terms",
          "centres",
          "sic_codes",
          "geography_sets",
          "suppressions"
        ],
        "description": "How the definition was run: expanded terms, resolved centres, SIC codes behind a business class and suppression checksums."
      },
      "ComplianceObject": {
        "type": "object",
        "properties": {
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ],
            "description": "UK GDPR Article 6(1)(f) legitimate interests, with the LIA in lia_ref."
          },
          "lia_ref": {
            "type": "string",
            "description": "The published legitimate interests assessment."
          },
          "subscriber_class": {
            "type": "string",
            "enum": [
              "ltd",
              "plc",
              "llp",
              "scottish_partnership",
              "public_body",
              "charity_incorporated",
              "sole_trader",
              "ordinary_partnership",
              "unknown"
            ],
            "description": "PECR subscriber class: ltd, plc, llp, scottish_partnership, public_body, charity_incorporated, sole_trader, ordinary_partnership, unknown."
          },
          "corporate_subscriber": {
            "type": "boolean",
            "description": "True for companies, LLPs, Scottish partnerships and public bodies, where the PECR regulation 22 consent rule does not apply."
          },
          "email_marketing_basis": {
            "type": "string",
            "enum": [
              "pecr_corporate_subscriber",
              "consent_required"
            ]
          },
          "subscriber_evidence": {
            "type": "object",
            "properties": {
              "companies_house_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "company_type": {
                "type": "string"
              }
            },
            "required": [
              "companies_house_number",
              "company_type"
            ],
            "description": "The register entry behind subscriber_class."
          },
          "article14_status": {
            "type": "string",
            "enum": [
              "notified",
              "publicly_notified_disproportionate_effort",
              "pending_within_window"
            ],
            "description": "Article 14 notice status: notified, publicly_notified_disproportionate_effort, pending_within_window."
          },
          "article14_notified_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "notice_version": {
            "type": "string",
            "description": "The privacy notice version sent."
          },
          "provenance": {
            "$ref": "#/components/schemas/Provenance"
          },
          "tps_ctps_status": {
            "type": "string",
            "enum": [
              "clear",
              "tps_registered",
              "ctps_registered",
              "tps_or_ctps_registered",
              "not_screened"
            ],
            "description": "Telephone screen: clear, tps_registered, ctps_registered, tps_or_ctps_registered, not_screened. The result of the screen on tps_ctps_screened_at, valid until tps_ctps_valid_until. In a sample, an order's records (each time they are fetched, downloaded or pushed) and an enrichment, a clear number reads not_screened, with no dates, once that screen is more than 28 days before the day the record is served; a registered number stays registered."
          },
          "tps_ctps_screened_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "The date of the screen the status is as of; null when not screened."
          },
          "tps_ctps_valid_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "28 days after tps_ctps_screened_at, when this screen stops being valid. Null when not screened. Screen the numbers you are supplied yourself before calling, and again every 28 days."
          },
          "suppression_status": {
            "type": "string",
            "enum": [
              "none",
              "objected_to_emailmovers",
              "objected_to_licensee",
              "deceased",
              "left_company"
            ]
          },
          "record_age_days": {
            "type": "integer",
            "minimum": 0,
            "description": "Days since the record was compiled."
          },
          "attribution": {
            "description": "The OGL v3.0 attribution for Companies House company data. Officer names are personal data outside the OGL, so they carry article14_status instead.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "lawful_basis",
          "lia_ref",
          "subscriber_class",
          "corporate_subscriber",
          "email_marketing_basis",
          "subscriber_evidence",
          "article14_status",
          "article14_notified_at",
          "notice_version",
          "provenance",
          "tps_ctps_status",
          "tps_ctps_screened_at",
          "tps_ctps_valid_until",
          "suppression_status",
          "record_age_days",
          "attribution"
        ],
        "description": "Carried by every preview row, order record, lookup and enrichment, and repeated as CSV columns and as the MyDataHub property group on CRM push.",
        "examples": [
          {
            "lawful_basis": "legitimate_interests_art6_1_f",
            "lia_ref": "EM-LIA-2026-03",
            "subscriber_class": "ltd",
            "corporate_subscriber": true,
            "email_marketing_basis": "pecr_corporate_subscriber",
            "subscriber_evidence": {
              "companies_house_number": "05046417",
              "company_type": "ltd"
            },
            "article14_status": "notified",
            "article14_notified_at": "2026-06-14",
            "notice_version": "2026-02",
            "provenance": {
              "company": {
                "source": "companies_house",
                "as_of": "2026-09-21"
              },
              "contact": {
                "source": "emailmovers_research",
                "compiled_at": "2026-05-02",
                "last_verified_at": "2026-08-30",
                "method": "telephone"
              },
              "email": {
                "verified_at": "2026-09-10",
                "result": "ok",
                "provider_location": "EU"
              }
            },
            "tps_ctps_status": "clear",
            "tps_ctps_screened_at": "2026-09-12",
            "tps_ctps_valid_until": "2026-10-10",
            "suppression_status": "none",
            "record_age_days": 147,
            "attribution": "Contains public sector information licensed under the Open Government Licence v3.0"
          }
        ]
      },
      "ComplianceReceipt": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^rcpt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a compliance receipt id: rcpt_ followed by a 26 character ULID in upper case Crockford base32, such as rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R.",
            "examples": [
              "rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R"
            ]
          },
          "order_id": {
            "type": "string",
            "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "examples": [
              "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
            ]
          },
          "jws": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$",
            "description": "The receipt as a compact JWS signed with ES256."
          },
          "alg": {
            "type": "string",
            "const": "ES256"
          },
          "kid": {
            "type": "string",
            "description": "The signing key id in jwks_url."
          },
          "jwks_url": {
            "type": "string",
            "format": "uri"
          },
          "pdf_url": {
            "type": "string",
            "format": "uri",
            "description": "The PDF twin at mydatahub.emailmovers.com/receipts/{id}."
          },
          "claims": {
            "$ref": "#/components/schemas/ReceiptClaims"
          }
        },
        "required": [
          "id",
          "order_id",
          "jws",
          "alg",
          "kid",
          "jwks_url",
          "pdf_url",
          "claims"
        ],
        "description": "A signed compliance receipt for an order, verifiable by anyone with POST /v1/compliance/receipts/verify."
      },
      "ComplianceSummary": {
        "type": "object",
        "properties": {
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ]
          },
          "corporate_subscriber": {
            "type": "integer",
            "minimum": 0,
            "description": "Records at corporate subscribers."
          },
          "individual_subscriber_excluded": {
            "type": "integer",
            "minimum": 0,
            "description": "Sole traders and ordinary partnerships left out of an email audience."
          },
          "tps_ctps_excluded": {
            "type": "integer",
            "minimum": 0,
            "description": "TPS or CTPS registered numbers left out when phone is requested."
          },
          "article14_notified": {
            "type": "integer",
            "minimum": 0
          },
          "article14_pending_within_window": {
            "type": "integer",
            "minimum": 0,
            "description": "Records inside the one month Article 14 window, not yet notified."
          },
          "suppressed_removed": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuppressionRemoval"
            }
          },
          "jurisdiction_excluded": {
            "description": "Partner datasets only: records the jurisdiction policy table left out (Germany, Canada and California by policy), reported like suppression removals.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JurisdictionExclusion"
            }
          }
        },
        "required": [
          "lawful_basis",
          "corporate_subscriber",
          "individual_subscriber_excluded",
          "tps_ctps_excluded",
          "article14_notified",
          "article14_pending_within_window",
          "suppressed_removed"
        ],
        "description": "Beside every count, so a person or an agent can reason before spending. Individual subscribers and TPS and CTPS registered numbers are excluded by default, as visible toggles; numbers not screened are kept."
      },
      "ConfirmationRequiredProblem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI under https://emailmovers.com/mydatahub/docs/errors/ naming the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short summary of the problem type."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "description": "What happened on this request, in plain English."
          },
          "instance": {
            "description": "The request path or a request id this problem belongs to.",
            "type": "string"
          },
          "code": {
            "type": "string",
            "const": "confirmation-required"
          },
          "next_step": {
            "type": "string",
            "description": "What to do next, in plain English."
          },
          "did_you_mean": {
            "description": "The closest valid values, best first.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "description": "For validation-failed: every problem found, each with a JSON pointer.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProblemError"
            }
          },
          "required_scope": {
            "description": "For insufficient-scope: the scope to request, such as orders:write.",
            "type": "string"
          },
          "retry_after_seconds": {
            "description": "For rate-limited and service-unavailable: the same value as the Retry-After header.",
            "type": "integer",
            "minimum": 0
          },
          "action": {
            "type": "string",
            "enum": [
              "order",
              "enrichment",
              "live_push"
            ],
            "description": "What needs confirming: an order, an enrichment or a live CRM push."
          },
          "quote_id": {
            "description": "For an order: the machine quote to keep. A person can approve it later.",
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "approval_url": {
            "type": "string",
            "format": "uri",
            "description": "A page on mydatahub.emailmovers.com where the signed-in person approves, such as mydatahub.emailmovers.com/quotes/{id}/approve. It returns a confirmation_token bound to that person (their sub), this spend and an expiry."
          },
          "expires_at": {
            "description": "When the approval page stops accepting: the machine quote's expiry.",
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "next_step",
          "action",
          "approval_url"
        ],
        "description": "403: no human confirmation came with a spend, and no agent key covers it. A standard API key or an OAuth token alone never spends. Nothing was charged and no order was created."
      },
      "ConfirmedBy": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "elicitation_form",
              "approval_url",
              "agent_key",
              "app"
            ],
            "description": "elicitation_form (the MCP form), approval_url (the approval page's confirmation_token), agent_key (a pre-authorised agent key within its limits) or app (a person ordering in the app itself, a first-party session; third-party OAuth clients never count)."
          },
          "key_id": {
            "description": "The agent key, for agent_key.",
            "type": "string",
            "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "examples": [
              "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "user_id": {
            "description": "The person who confirmed.",
            "type": "string",
            "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "examples": [
              "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "client_id": {
            "description": "The OAuth client, such as a Client ID Metadata Document URL.",
            "type": "string"
          },
          "user_agent": {
            "description": "The calling client's User-Agent.",
            "type": [
              "string",
              "null"
            ]
          },
          "mtls_certificate_fingerprint": {
            "description": "SHA-256 of the client certificate when one was presented (ChatGPT's mTLS).",
            "type": [
              "string",
              "null"
            ]
          },
          "web_bot_auth_signature_agent": {
            "description": "The Signature-Agent of a verified Web Bot Auth signature, when present.",
            "type": [
              "string",
              "null"
            ]
          },
          "confirmed_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "method"
        ],
        "description": "Who approved the spend and from which client, recorded in the audit trail and on invoices."
      },
      "Connection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
            "examples": [
              "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "hubspot",
              "salesforce",
              "google_sheets",
              "deliverite",
              "webhook",
              "csv"
            ]
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_authorisation",
              "connected",
              "expired",
              "revoked"
            ]
          },
          "authorise_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where a person authorises the connection in the app, while pending_authorisation."
          },
          "read_only_overlap": {
            "type": "boolean",
            "description": "Whether the connection may read email hashes for the New to you overlap check."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "provider",
          "name",
          "status",
          "authorise_url",
          "read_only_overlap",
          "created_at",
          "last_used_at"
        ],
        "description": "A CRM or destination connection."
      },
      "ConnectionExpiredEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "connection.expired"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "type": "object",
            "properties": {
              "connection_id": {
                "type": "string",
                "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
                "examples": [
                  "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
                ]
              },
              "provider": {
                "type": "string"
              },
              "reconnect_url": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "connection_id",
              "provider",
              "reconnect_url"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A CRM token failed; reconnect in the app."
      },
      "ConnectionList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Connection"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of CRM connections, newest first."
      },
      "ConnectionRequest": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "hubspot",
              "salesforce",
              "google_sheets",
              "deliverite",
              "webhook",
              "csv"
            ]
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "webhook_url": {
            "description": "Provider webhook only, and required there: the https endpoint to post to.",
            "type": "string",
            "format": "uri",
            "pattern": "^https://"
          }
        },
        "required": [
          "provider",
          "name"
        ],
        "additionalProperties": false,
        "description": "A new connection. OAuth providers return an authorise_url for a person to approve; provider webhook takes webhook_url.",
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "provider": {
                  "const": "webhook"
                }
              },
              "required": [
                "provider"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "webhook_url": true
              },
              "required": [
                "webhook_url"
              ]
            },
            "else": {
              "type": "object",
              "not": {
                "type": "object",
                "properties": {
                  "webhook_url": true
                },
                "required": [
                  "webhook_url"
                ]
              }
            }
          }
        ]
      },
      "ContactRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "The record id, pushed to CRMs as mydatahub_record_id.",
            "examples": [
              "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "contact": {
            "type": "object",
            "properties": {
              "first_name": {
                "type": "string"
              },
              "last_name": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "title_family": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "job_function": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "job_level_rank": {
                "anyOf": [
                  {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 13
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Rank on the 13-rank ladder, 1 (Owner) the most senior to 13 (Volunteer); null when the level is not known."
              },
              "job_level": {
                "description": "The level, such as Director; null when the level is not known.",
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "first_name",
              "last_name",
              "title",
              "title_family",
              "job_function",
              "job_level_rank",
              "job_level"
            ]
          },
          "email": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "format": "email"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "named",
                      "generic_local_part",
                      "generic_domain"
                    ]
                  },
                  "deliverability_score": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "verified_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "result": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "catch_all",
                      "unknown",
                      "invalid",
                      "disposable"
                    ]
                  }
                },
                "required": [
                  "address",
                  "type",
                  "deliverability_score",
                  "verified_at",
                  "result"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "phone": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "e164": {
                    "type": "string",
                    "pattern": "^\\+[1-9][0-9]{7,14}$"
                  },
                  "line_type": {
                    "type": "string",
                    "enum": [
                      "landline",
                      "mobile",
                      "voip",
                      "unknown"
                    ]
                  },
                  "tps_ctps_status": {
                    "type": "string",
                    "enum": [
                      "clear",
                      "tps_registered",
                      "ctps_registered",
                      "tps_or_ctps_registered",
                      "not_screened"
                    ]
                  },
                  "screened_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "e164",
                  "line_type",
                  "tps_ctps_status",
                  "screened_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when the field set includes telephone and a number is held."
          },
          "company": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "companies_house_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "subscriber_class": {
                "type": "string",
                "enum": [
                  "ltd",
                  "plc",
                  "llp",
                  "scottish_partnership",
                  "public_body",
                  "charity_incorporated",
                  "sole_trader",
                  "ordinary_partnership",
                  "unknown"
                ]
              },
              "sic_2007": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SicCode"
                }
              },
              "employee_band": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "turnover_band": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "website_domain": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "companies_house_number",
              "status",
              "type",
              "subscriber_class",
              "sic_2007",
              "employee_band",
              "turnover_band",
              "website_domain"
            ]
          },
          "site": {
            "type": "object",
            "properties": {
              "address_lines": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "town": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "county": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "postcode": {
                "type": "string"
              },
              "region": {
                "type": "string"
              }
            },
            "required": [
              "address_lines",
              "town",
              "county",
              "postcode",
              "region"
            ]
          },
          "compliance": {
            "$ref": "#/components/schemas/ComplianceObject"
          },
          "licence_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "dataset_version",
          "contact",
          "email",
          "phone",
          "company",
          "site",
          "compliance",
          "licence_expires_at"
        ],
        "description": "One complete UK record: named email, telephone where held, postal address and company fields with Companies House number and SIC, plus the compliance object."
      },
      "Count": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "engine_rules_version": {
            "type": "string",
            "minLength": 1,
            "description": "The engine rules (title expansion, defaults, geography sets) the count ran under; part of what the count id hashes, such as 2026.09.1."
          },
          "as_of": {
            "description": "The date the dataset version was built, for as-of statements.",
            "type": "string",
            "format": "date"
          },
          "level": {
            "type": "string",
            "enum": [
              "contact",
              "company"
            ],
            "description": "contact (the default) or company. Contacts and companies come back together either way."
          },
          "credits_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "contacts": {
            "type": "integer",
            "minimum": 0,
            "description": "Total: every matching contact."
          },
          "companies": {
            "type": "integer",
            "minimum": 0
          },
          "emailable": {
            "type": "integer",
            "minimum": 0,
            "description": "A named email scoring 70 or more at a corporate subscriber."
          },
          "new_to_you": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "Excludes your earlier orders and CRM overlap; null when signed out."
          },
          "premium": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "Premium: the contacts of all_records that are premium records (contact.premium true). At launch, a premium record is in the premium export of a stated date. Null when the dataset version carries no premium data, or withheld when the premium records are at a single company and the caller has no account; premium_note says which."
          },
          "all_records": {
            "type": "integer",
            "minimum": 0,
            "description": "All records: every matching contact with the audience's top-level premium filters taken out (a premium filter inside any or not stays), so the premium figure always has the full figure beside it. The same as contacts when the audience has no premium filter."
          },
          "premium_note": {
            "type": "string",
            "minLength": 1,
            "description": "What premium means on this dataset version, or why premium is null: no premium data on the version, or withheld because the premium records are at a single company."
          },
          "views": {
            "$ref": "#/components/schemas/CountViews"
          },
          "quality": {
            "$ref": "#/components/schemas/Quality"
          },
          "breakdowns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Breakdown"
            }
          },
          "crosstab": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Crosstab"
              },
              {
                "type": "null"
              }
            ]
          },
          "compliance_summary": {
            "$ref": "#/components/schemas/ComplianceSummary"
          },
          "defaults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CountDefault"
            },
            "description": "Every default with the number behind its toggle: dissolved and insolvent, generic emails, individual subscribers, TPS and CTPS registered."
          },
          "estimate": {
            "$ref": "#/components/schemas/PriceEstimate"
          },
          "expanded_terms": {
            "description": "Every title a matches filter covered, with a count per term.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpandedTerm"
            }
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          },
          "effective_audience": {
            "description": "The definition after defaults and bundles, as hashed into the id.",
            "$ref": "#/components/schemas/Audience"
          },
          "plan": {
            "$ref": "#/components/schemas/CompiledPlan"
          },
          "current": {
            "description": "On a replay: the same audience on the current dataset version.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/CurrentCount"
              },
              {
                "type": "null"
              }
            ]
          },
          "removed_since": {
            "description": "On a replay: records since removed by objections and erasure.",
            "type": "integer",
            "minimum": 0
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "The id replays until then (12 months)."
          }
        },
        "required": [
          "id",
          "dataset",
          "dataset_version",
          "engine_rules_version",
          "credits_per_record",
          "contacts",
          "companies",
          "emailable",
          "new_to_you",
          "premium",
          "all_records",
          "premium_note",
          "quality",
          "breakdowns",
          "compliance_summary",
          "defaults",
          "estimate",
          "disclosure",
          "expires_at"
        ],
        "description": "Total, New to you and Emailable, the premium figure beside all records, with companies, breakdowns, quality, the compliance summary, the defaults behind the toggles, disclosure and a price estimate. The id is content addressed, so the same definition from chips, REST or MCP gives the same id."
      },
      "CountDefault": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "active_companies",
              "named_emails",
              "corporate_subscribers",
              "no_registered_phones"
            ],
            "description": "active_companies, named_emails, corporate_subscribers or no_registered_phones."
          },
          "applied": {
            "type": "boolean",
            "description": "False when the audience filters the same field itself, or turned it off."
          },
          "views": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "total",
                "new_to_you",
                "emailable"
              ]
            },
            "description": "The headline views the default shapes; named emails and corporate subscribers shape Emailable only."
          },
          "removed": {
            "description": "What the toggle shows: the dissolved and insolvent count, the generic (info@, sales@) count, the individual subscriber count or the TPS and CTPS registered count.",
            "$ref": "#/components/schemas/CellCount"
          },
          "screened_at": {
            "description": "no_registered_phones only: the version's TPS and CTPS screen date.",
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "applied",
          "views",
          "removed"
        ],
        "description": "A default the count applied, and the records it removed, for its toggle."
      },
      "CountReplay": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "engine_rules_version": {
            "type": "string",
            "minLength": 1,
            "description": "The engine rules (title expansion, defaults, geography sets) the count ran under; part of what the count id hashes, such as 2026.09.1."
          },
          "as_of": {
            "description": "The date the dataset version was built, for as-of statements.",
            "type": "string",
            "format": "date"
          },
          "level": {
            "type": "string",
            "enum": [
              "contact",
              "company"
            ],
            "description": "contact (the default) or company. Contacts and companies come back together either way."
          },
          "credits_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "contacts": {
            "type": "integer",
            "minimum": 0,
            "description": "Total: every matching contact."
          },
          "companies": {
            "type": "integer",
            "minimum": 0
          },
          "emailable": {
            "type": "integer",
            "minimum": 0,
            "description": "A named email scoring 70 or more at a corporate subscriber."
          },
          "new_to_you": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "Excludes your earlier orders and CRM overlap; null when signed out."
          },
          "premium": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "Premium: the contacts of all_records that are premium records (contact.premium true). At launch, a premium record is in the premium export of a stated date. Null when the dataset version carries no premium data, or withheld when the premium records are at a single company and the caller has no account; premium_note says which."
          },
          "all_records": {
            "type": "integer",
            "minimum": 0,
            "description": "All records: every matching contact with the audience's top-level premium filters taken out (a premium filter inside any or not stays), so the premium figure always has the full figure beside it. The same as contacts when the audience has no premium filter."
          },
          "premium_note": {
            "type": "string",
            "minLength": 1,
            "description": "What premium means on this dataset version, or why premium is null: no premium data on the version, or withheld because the premium records are at a single company."
          },
          "views": {
            "$ref": "#/components/schemas/CountViews"
          },
          "quality": {
            "$ref": "#/components/schemas/Quality"
          },
          "breakdowns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Breakdown"
            }
          },
          "crosstab": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Crosstab"
              },
              {
                "type": "null"
              }
            ]
          },
          "compliance_summary": {
            "$ref": "#/components/schemas/ComplianceSummary"
          },
          "defaults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CountDefault"
            },
            "description": "Every default with the number behind its toggle: dissolved and insolvent, generic emails, individual subscribers, TPS and CTPS registered."
          },
          "estimate": {
            "$ref": "#/components/schemas/PriceEstimate"
          },
          "expanded_terms": {
            "description": "Every title a matches filter covered, with a count per term.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpandedTerm"
            }
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          },
          "effective_audience": {
            "description": "The definition after defaults and bundles, as hashed into the id.",
            "$ref": "#/components/schemas/Audience"
          },
          "plan": {
            "$ref": "#/components/schemas/CompiledPlan"
          },
          "current": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CurrentCount"
              },
              {
                "type": "null"
              }
            ],
            "description": "The same audience on the current dataset version; null when the pinned version is current."
          },
          "removed_since": {
            "type": "integer",
            "minimum": 0,
            "description": "Records since removed by objections and erasure."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "The id replays until then (12 months)."
          }
        },
        "required": [
          "id",
          "dataset",
          "dataset_version",
          "engine_rules_version",
          "credits_per_record",
          "contacts",
          "companies",
          "emailable",
          "new_to_you",
          "premium",
          "all_records",
          "premium_note",
          "views",
          "quality",
          "breakdowns",
          "compliance_summary",
          "defaults",
          "estimate",
          "disclosure",
          "effective_audience",
          "plan",
          "current",
          "removed_since",
          "created_at",
          "expires_at"
        ],
        "description": "A count replayed by id for 12 months: the effective definition, the compiled plan, the pinned dataset and engine rules versions, all three views with premium and all records, the breakdowns, the compliance summary, quality, the estimate, created_at and the number on the current dataset."
      },
      "CountRequest": {
        "type": "object",
        "properties": {
          "audience": {
            "$ref": "#/components/schemas/AudienceRef"
          },
          "level": {
            "default": "contact",
            "type": "string",
            "enum": [
              "contact",
              "company"
            ],
            "description": "contact (the default) or company. Contacts and companies come back together either way."
          },
          "breakdown_by": {
            "maxItems": 3,
            "type": "array",
            "items": {
              "type": "string",
              "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"
              ],
              "description": "A field a count can be broken down by."
            },
            "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
          }
        },
        "required": [
          "audience"
        ],
        "additionalProperties": false,
        "description": "An audience, a level and up to three breakdown fields. Free, and needs no account."
      },
      "CountView": {
        "type": "object",
        "properties": {
          "contacts": {
            "type": "integer",
            "minimum": 0
          },
          "companies": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "contacts",
          "companies"
        ],
        "description": "Contacts and companies in one headline view."
      },
      "CountViews": {
        "type": "object",
        "properties": {
          "total": {
            "$ref": "#/components/schemas/CountView"
          },
          "new_to_you": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CountView"
              },
              {
                "type": "null"
              }
            ],
            "description": "Removes records from earlier orders and a connected CRM; null when signed out."
          },
          "emailable": {
            "description": "A named email scoring 70 or more at a corporate subscriber.",
            "$ref": "#/components/schemas/CountView"
          },
          "premium": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CountView"
              },
              {
                "type": "null"
              }
            ],
            "description": "The premium records of all_records (contact.premium true); null when the dataset version carries no premium data, or withheld when they are at a single company and the caller has no account."
          },
          "all_records": {
            "description": "The full figure: the audience with its top-level premium filters taken out (one inside any or not stays). The same as total when it has none.",
            "$ref": "#/components/schemas/CountView"
          }
        },
        "required": [
          "total",
          "new_to_you",
          "emailable",
          "premium",
          "all_records"
        ],
        "description": "Contacts and companies for the three headline views, and the premium figure beside all records."
      },
      "CreditPack": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "Such as free, pay_as_you_go or plan_12_month."
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "const": "pack"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed",
              "to_confirm"
            ],
            "description": "confirmed is in force; proposed awaits a decision; to_confirm is a figure still being checked."
          },
          "available_to": {
            "type": "string",
            "enum": [
              "everyone",
              "new_customers",
              "existing_customers"
            ],
            "description": "everyone; new_customers only (the subscription); existing_customers only, who keep their prices (pay as you go and the 12-month plan)."
          },
          "price_gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "billing_period": {
            "type": "string",
            "const": "once"
          },
          "contract_months": {
            "description": "The contract's length in months, such as 12; absent when there is none.",
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "annual_price_gbp_ex_vat": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "description": "Pounds sterling excluding VAT, to two decimal places."
              },
              {
                "type": "null"
              }
            ]
          },
          "credits": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits per billing period, or once."
          },
          "per_record_gbp": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "description": "Pounds sterling excluding VAT, to two decimal places."
              },
              {
                "type": "null"
              }
            ],
            "description": "Price per record at full use of the allowance; null for the free plan."
          },
          "rollover_cap_credits": {
            "description": "Subscription credits roll over while subscribed, up to this many; 0 when each period's credits are used or lost.",
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "credits_expire": {
            "type": "boolean"
          },
          "for_whom": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "status",
          "available_to",
          "price_gbp_ex_vat",
          "billing_period",
          "credits",
          "per_record_gbp",
          "credits_expire",
          "for_whom"
        ],
        "description": "A one-off prepaid bundle of credits, usable on any plan. Credit pack credits never expire and survive cancellation."
      },
      "CreditPurchase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^pur_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a credit purchase id: pur_ followed by a 26 character ULID in upper case Crockford base32, such as pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "pur_01JB4R7K2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "paid",
              "expired"
            ],
            "description": "pending until Stripe says the payment is paid; paid once the credits are in the balance; expired when the checkout closed unpaid (nothing was taken)."
          },
          "label": {
            "type": "string",
            "description": "What is bought, in words, numbers first."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditPurchaseLine"
            }
          },
          "credits": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits the purchase adds when paid."
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "vat_rate_percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "vat_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling, to two decimal places."
          },
          "total_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "What the card is charged, VAT included."
          },
          "currency": {
            "type": "string",
            "const": "GBP"
          },
          "gbp_per_credit": {
            "type": "number",
            "minimum": 0,
            "description": "What one credit of this purchase cost, excluding VAT, to six decimal places. Orders value the credits they spend at it."
          },
          "credits_added": {
            "type": "integer",
            "minimum": 0,
            "description": "0 until the payment is paid."
          },
          "checkout_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "Stripe Checkout, while the purchase is pending; null once paid or expired."
          },
          "test_mode": {
            "type": "boolean",
            "description": "Made with a Stripe test key: test cards only, and no money moves."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the checkout closes if it is not paid."
          },
          "paid_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "attention": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PurchaseAttention"
              },
              {
                "type": "null"
              }
            ]
          },
          "receipt": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PaymentReceipt"
              },
              {
                "type": "null"
              }
            ],
            "description": "Once paid. The buyer's name, billing address and VAT number are shown only to a signed-in person with admin; anyone else sees them as null."
          }
        },
        "required": [
          "id",
          "status",
          "label",
          "lines",
          "credits",
          "gbp_ex_vat",
          "vat_rate_percent",
          "vat_gbp",
          "total_gbp",
          "currency",
          "gbp_per_credit",
          "credits_added",
          "checkout_url",
          "test_mode",
          "created_at",
          "expires_at",
          "paid_at",
          "attention",
          "receipt"
        ],
        "description": "A purchase of credits by card through Stripe Checkout. Reading a pending purchase asks Stripe for its payment (at most once every 10 seconds), and adds the credits once, when it is paid."
      },
      "CreditPurchaseLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "per_contact_scale or a credit pack id."
          },
          "quantity": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits at the scale, or credit packs."
          },
          "credits": {
            "type": "integer",
            "minimum": 0
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          }
        },
        "required": [
          "id",
          "quantity",
          "credits",
          "gbp_ex_vat"
        ],
        "description": "One line of a purchase, priced."
      },
      "CreditPurchaseLineRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "per_contact_scale for credits at the scale, or the id of a credit pack on sale, such as credit_pack_40000 (GET /v1/plans)."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000000,
            "description": "Credits at the scale (1 to 1,000,000), or credit packs (1 to 25)."
          }
        },
        "required": [
          "id",
          "quantity"
        ],
        "additionalProperties": false,
        "description": "One thing to buy."
      },
      "CreditPurchaseList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditPurchase"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          },
          "payments": {
            "type": "object",
            "properties": {
              "available": {
                "type": "boolean",
                "description": "Whether card payments are switched on for this server."
              },
              "test_mode": {
                "type": "boolean",
                "description": "Stripe test mode: test cards only."
              },
              "vat_rate_percent": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              }
            },
            "required": [
              "available",
              "test_mode",
              "vat_rate_percent"
            ],
            "description": "How credits are bought here."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor",
          "payments"
        ],
        "description": "A page of credit purchases, newest first, and whether card payments are on."
      },
      "CreditPurchaseRequest": {
        "type": "object",
        "properties": {
          "lines": {
            "minItems": 1,
            "maxItems": 5,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditPurchaseLineRequest"
            },
            "description": "What to buy: credits at the scale, credit packs, or both, as a quote's purchase option lists them. Each id at most once."
          }
        },
        "required": [
          "lines"
        ],
        "additionalProperties": false,
        "description": "A top-up of credits at the per-contact scale (the size of the line picks its band), the 40,000 credit pack, or a quote's purchase option line by line."
      },
      "CreditRule": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
          },
          "label": {
            "type": "string"
          },
          "credits": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "unit": {
            "type": "string",
            "enum": [
              "call",
              "record",
              "match"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed",
              "to_confirm"
            ],
            "description": "confirmed is in force; proposed awaits a decision; to_confirm is a figure still being checked."
          },
          "note": {
            "type": "string"
          }
        },
        "required": [
          "action",
          "label",
          "credits",
          "unit",
          "status"
        ],
        "description": "What one action costs in credits."
      },
      "CreditsLowEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "credits.low"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "type": "object",
            "properties": {
              "balance": {
                "type": "number"
              },
              "threshold": {
                "type": "integer",
                "minimum": 0
              },
              "top_up_url": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "balance",
              "threshold",
              "top_up_url"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "The balance crossed the configured threshold."
      },
      "CreditsToppedUpEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "credits.topped_up"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "type": "object",
            "properties": {
              "credits_added": {
                "type": "integer",
                "minimum": 0
              },
              "balance": {
                "type": "number"
              },
              "source": {
                "type": "string",
                "enum": [
                  "credit_pack",
                  "top_up",
                  "plan",
                  "refund",
                  "adjustment"
                ],
                "description": "credit_pack for credit packs bought by card, top_up for credits bought at the per-contact scale (with or without credit packs), plan for a plan's credits, refund or adjustment."
              },
              "amount_gbp_ex_vat": {
                "anyOf": [
                  {
                    "type": "number",
                    "minimum": 0,
                    "description": "Pounds sterling excluding VAT, to two decimal places."
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "credits_added",
              "balance",
              "source",
              "amount_gbp_ex_vat"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A top-up settled."
      },
      "CrmPropertyGroup": {
        "type": "object",
        "properties": {
          "mydatahub_record_id": {
            "type": "string",
            "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "The record id: a Salesforce External ID, a HubSpot unique property, a Pipedrive custom field.",
            "examples": [
              "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "licence_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ]
          },
          "article14_status": {
            "type": "string",
            "enum": [
              "notified",
              "publicly_notified_disproportionate_effort",
              "pending_within_window"
            ]
          },
          "tps_ctps_screened_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "subscriber_class": {
            "type": "string",
            "enum": [
              "ltd",
              "plc",
              "llp",
              "scottish_partnership",
              "public_body",
              "charity_incorporated",
              "sole_trader",
              "ordinary_partnership",
              "unknown"
            ]
          },
          "suppression_status": {
            "type": "string",
            "enum": [
              "none",
              "objected_to_emailmovers",
              "objected_to_licensee",
              "deceased",
              "left_company"
            ],
            "description": "Kept current: an objection reaching the record updates it in the CRM."
          },
          "compliance_receipt_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "mydatahub_record_id",
          "licence_expires_at",
          "lawful_basis",
          "article14_status",
          "tps_ctps_screened_at",
          "subscriber_class",
          "suppression_status",
          "compliance_receipt_url"
        ],
        "description": "The MyDataHub property group written on every pushed record, so licence expiry and suppression are enforced in the CRM by field flags."
      },
      "Crosstab": {
        "type": "object",
        "properties": {
          "by": {
            "minItems": 2,
            "maxItems": 3,
            "type": "array",
            "items": {
              "type": "string",
              "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"
              ],
              "description": "A field a count can be broken down by."
            }
          },
          "cells": {
            "maxItems": 5000,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CrosstabCell"
            }
          },
          "other": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OtherBucket"
              },
              {
                "type": "null"
              }
            ]
          },
          "truncated": {
            "type": "boolean",
            "description": "True when a cap cut the table: 5,000 cells, or fewer over MCP to keep a result under about 8,000 tokens."
          }
        },
        "required": [
          "by",
          "cells",
          "other",
          "truncated"
        ],
        "description": "Two or three fields as one grouped table (industry by seniority by region), top 50 values per field, capped at 5,000 cells. For anonymous and trial callers, secondary suppression hides enough further cells, each reading \"suppressed\", that no total can be differenced to reveal a cell under 10."
      },
      "CrosstabCell": {
        "type": "object",
        "properties": {
          "values": {
            "minItems": 2,
            "maxItems": 3,
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            }
          },
          "filter_values": {
            "description": "The values filters take, when any differs from values (ranks for seniority).",
            "minItems": 2,
            "maxItems": 3,
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            }
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          }
        },
        "required": [
          "values",
          "contacts"
        ],
        "description": "One cell of a cross-tab, one value per field."
      },
      "CurrentCount": {
        "type": "object",
        "properties": {
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "contacts": {
            "type": "integer",
            "minimum": 0
          },
          "companies": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "dataset_version",
          "contacts",
          "companies"
        ],
        "description": "The same audience on the current dataset version."
      },
      "Dataset": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "planned",
              "through_our_team"
            ],
            "description": "live is served; planned is not yet served; through_our_team is sold through the bespoke service only."
          },
          "owner": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "licence": {
            "type": "string"
          },
          "refresh": {
            "type": "string"
          },
          "residency": {
            "type": "string"
          },
          "regulator": {
            "type": "string"
          },
          "warranty": {
            "type": "string"
          },
          "credits_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "1 for owned UK and Irish data."
          },
          "credits_status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed"
            ]
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
                "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
                "examples": [
                  "2026-W39"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "versions_available": {
            "type": "integer",
            "minimum": 0,
            "description": "Immutable weekly versions still queryable (the last 52)."
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "owner",
          "source",
          "licence",
          "refresh",
          "residency",
          "regulator",
          "warranty",
          "credits_per_record",
          "credits_status",
          "current_version",
          "versions_available"
        ],
        "description": "A dataset with owner, source, licence, refresh, residency, regulator, warranty and credits per record."
      },
      "DatasetList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dataset"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of datasets, newest first."
      },
      "DatasetVersionChangelog": {
        "type": "object",
        "properties": {
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "built_at": {
            "type": "string",
            "format": "date-time"
          },
          "checksum": {
            "type": "string",
            "description": "SHA-256 over the version's files."
          },
          "row_counts": {
            "type": "object",
            "properties": {
              "companies": {
                "type": "integer",
                "minimum": 0
              },
              "sites": {
                "type": "integer",
                "minimum": 0
              },
              "contacts": {
                "type": "integer",
                "minimum": 0
              },
              "emails": {
                "type": "integer",
                "minimum": 0
              },
              "phones": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "companies",
              "sites",
              "contacts",
              "emails",
              "phones"
            ]
          },
          "changes": {
            "type": "object",
            "properties": {
              "records_added": {
                "type": "integer",
                "minimum": 0
              },
              "records_retired": {
                "type": "integer",
                "minimum": 0
              },
              "records_reverified": {
                "type": "integer",
                "minimum": 0
              },
              "companies_dissolved": {
                "type": "integer",
                "minimum": 0
              },
              "job_changes_confirmed": {
                "type": "integer",
                "minimum": 0
              },
              "suppressions_applied": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "records_added",
              "records_retired",
              "records_reverified",
              "companies_dissolved",
              "job_changes_confirmed",
              "suppressions_applied"
            ]
          },
          "coverage_pct": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
            },
            "additionalProperties": {
              "type": "number",
              "minimum": 0,
              "maximum": 100
            },
            "description": "Share of contacts holding each field, such as named_email."
          },
          "input_snapshots": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string"
                },
                "as_of": {
                  "type": "string",
                  "format": "date"
                }
              },
              "required": [
                "source",
                "as_of"
              ]
            }
          }
        },
        "required": [
          "dataset",
          "version",
          "built_at",
          "checksum",
          "row_counts",
          "changes",
          "coverage_pct",
          "input_snapshots"
        ],
        "description": "What changed in one immutable weekly build, and the inputs it was built from."
      },
      "Disclosure": {
        "type": "object",
        "properties": {
          "level": {
            "type": "string",
            "enum": [
              "exact",
              "rounded"
            ],
            "description": "exact for authenticated paid callers; rounded for anonymous and trial callers, whose counts under 100 and every cell are rounded to the nearest 5."
          },
          "rounded_to": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "5 when numbers are rounded; null when they are exact."
          },
          "secondary_suppression": {
            "type": "boolean",
            "description": "True when cross-tab or breakdown cells of 10 or more were hidden as \"suppressed\" so totals cannot be differenced."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "level",
          "rounded_to",
          "secondary_suppression",
          "notes"
        ],
        "description": "Whether these numbers are exact or protected: \"under 10\" cells, rounding to 5 and secondary suppression for anonymous and trial callers."
      },
      "EmailPolicy": {
        "type": "object",
        "properties": {
          "min_deliverability_score": {
            "description": "Lowest deliverability score counted, 0 to 100. Default 70.",
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "allow_catch_all": {
            "description": "Whether catch-all addresses count. Default false.",
            "type": "boolean"
          }
        },
        "additionalProperties": false,
        "description": "Email quality floor. Defaults: min_deliverability_score 70, allow_catch_all false."
      },
      "EnrichRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "first_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "last_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "company_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "company_number": {
            "type": "string",
            "pattern": "^[A-Z0-9]{8}$",
            "description": "Eight characters in upper case, such as 05046417 or SC123456."
          },
          "domain": {
            "type": "string",
            "minLength": 3,
            "maxLength": 253
          },
          "confirmation_token": {
            "type": "string",
            "minLength": 16,
            "maxLength": 2000,
            "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."
          },
          "licence_accepted_version": {
            "description": "The version of the Data Licence and Sharing Agreement the person accepted for this record: the account's agreements.dlsa.version. Required when a person enriches in the app; an agent key carries the acceptance made with it, and a confirmation_token the one made on the approval page.",
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "additionalProperties": false,
        "description": "One known person to match. Send email, or first_name and last_name with company_name, company_number or domain.",
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "email": true
            },
            "required": [
              "email"
            ]
          },
          {
            "type": "object",
            "properties": {
              "first_name": true,
              "last_name": true
            },
            "required": [
              "first_name",
              "last_name"
            ],
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "company_name": true
                },
                "required": [
                  "company_name"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "company_number": true
                },
                "required": [
                  "company_number"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "domain": true
                },
                "required": [
                  "domain"
                ]
              }
            ]
          }
        ]
      },
      "Enrichment": {
        "type": "object",
        "properties": {
          "matched": {
            "type": "boolean"
          },
          "match_confidence": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              {
                "type": "null"
              }
            ]
          },
          "already_licensed": {
            "type": "boolean",
            "description": "True when you already hold the record, so it costs 0."
          },
          "record": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ContactRecord"
              },
              {
                "type": "null"
              }
            ]
          },
          "credits_charged": {
            "type": "number",
            "minimum": 0,
            "description": "1 on a confident match, otherwise 0."
          },
          "credits_remaining": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "cost_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "licence_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "matched",
          "match_confidence",
          "already_licensed",
          "record",
          "credits_charged",
          "credits_remaining",
          "cost_gbp",
          "licence_expires_at"
        ],
        "description": "The full record for a confident match, or no match at no charge."
      },
      "EventList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of events, oldest first."
      },
      "ExpandedTerm": {
        "type": "object",
        "properties": {
          "term": {
            "type": "string",
            "description": "A matched title."
          },
          "from_term": {
            "type": "string",
            "description": "The input term it came from."
          },
          "expansion_set": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "plural_singular",
                  "department_synonyms",
                  "ampersand_and",
                  "abbreviations",
                  "permutations"
                ]
              },
              {
                "type": "string",
                "const": "input"
              }
            ],
            "description": "The expansion set that produced it, or input for the term itself."
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          },
          "excluded": {
            "description": "True when exclude_terms removed it from the audience.",
            "type": "boolean"
          }
        },
        "required": [
          "term",
          "from_term",
          "expansion_set",
          "contacts"
        ],
        "description": "One title a matches filter covers, with its count."
      },
      "FieldSet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "Such as standard, standard_telephone or full."
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "credits_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "Every field set costs 1 credit a record."
          },
          "columns": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              },
              "required": [
                "name",
                "description"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "credits_per_record",
          "columns"
        ],
        "description": "The named bundle of fields delivered with an order, with its exact columns."
      },
      "FieldSetList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldSet"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of field sets, newest first."
      },
      "Filter": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/InFilter"
          },
          {
            "$ref": "#/components/schemas/BetweenFilter"
          },
          {
            "$ref": "#/components/schemas/GteFilter"
          },
          {
            "$ref": "#/components/schemas/LteFilter"
          },
          {
            "$ref": "#/components/schemas/MatchesFilter"
          },
          {
            "$ref": "#/components/schemas/WithinRadiusFilter"
          },
          {
            "$ref": "#/components/schemas/InListFilter"
          },
          {
            "$ref": "#/components/schemas/SinceFilter"
          }
        ],
        "description": "One criterion: a field from GET /v1/catalogue/filters, an operator and its operands. Exclusions nest under not.",
        "discriminator": {
          "propertyName": "op",
          "mapping": {
            "in": "#/components/schemas/InFilter",
            "between": "#/components/schemas/BetweenFilter",
            "gte": "#/components/schemas/GteFilter",
            "lte": "#/components/schemas/LteFilter",
            "matches": "#/components/schemas/MatchesFilter",
            "within_radius": "#/components/schemas/WithinRadiusFilter",
            "in_list": "#/components/schemas/InListFilter",
            "since": "#/components/schemas/SinceFilter"
          }
        }
      },
      "FilterCatalogue": {
        "type": "object",
        "properties": {
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilterDimension"
            }
          },
          "operators": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OperatorInfo"
            }
          },
          "datasets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dataset"
            }
          }
        },
        "required": [
          "dataset",
          "dataset_version",
          "fields",
          "operators",
          "datasets"
        ],
        "description": "Every filterable field with its type, operators and value count, plus the datasets."
      },
      "FilterDimension": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "description": "The field name, also the dimension slug."
          },
          "group": {
            "type": "string",
            "enum": [
              "company",
              "site",
              "contact",
              "email",
              "phone",
              "signal"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "enum",
              "text",
              "number",
              "date",
              "geo",
              "hashed_list",
              "boolean",
              "band"
            ]
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "operators": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "in",
                "between",
                "gte",
                "lte",
                "matches",
                "within_radius",
                "in_list",
                "since"
              ]
            }
          },
          "facet": {
            "type": "boolean",
            "description": "Usable in breakdown_by."
          },
          "value_count": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "Distinct values in this dataset version; null for free text and numbers."
          },
          "default": {
            "type": [
              "string",
              "null"
            ]
          },
          "examples": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            }
          },
          "values_url": {
            "description": "Where to search the values, or null when the field has none to list.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "field",
          "group",
          "type",
          "label",
          "description",
          "operators",
          "facet",
          "value_count",
          "default",
          "examples",
          "values_url"
        ],
        "description": "One filterable field."
      },
      "FilterValue": {
        "type": "object",
        "properties": {
          "code": {
            "description": "The value to use in a filter.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "label": {
            "type": "string"
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          },
          "companies": {
            "$ref": "#/components/schemas/CellCount"
          },
          "parent": {
            "description": "The parent code for hierarchical fields, such as SIC division 62 under J.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "code",
          "label",
          "contacts",
          "companies"
        ],
        "description": "One value of a field, with its counts."
      },
      "FilterValueList": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilterValue"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ]
          },
          "did_you_mean": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          }
        },
        "required": [
          "field",
          "dataset_version",
          "data",
          "has_more",
          "next_cursor",
          "disclosure"
        ],
        "description": "A page of values in one field, best match first when q is given."
      },
      "GteFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "company.employee_band",
              "company.turnover_band",
              "company.fleet_band",
              "contact.job_level_rank",
              "email.deliverability_score"
            ]
          },
          "op": {
            "type": "string",
            "const": "gte"
          },
          "value": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              {
                "type": "number"
              }
            ],
            "description": "A band code or a number from the field's order."
          }
        },
        "required": [
          "field",
          "op",
          "value"
        ],
        "additionalProperties": false,
        "description": "The field is at or after the value in its order: for bands, the band and every larger one.",
        "examples": [
          {
            "field": "company.employee_band",
            "op": "gte",
            "value": "50-99"
          }
        ],
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.employee_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string",
                  "enum": [
                    "1-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100-199",
                    "200-349",
                    "350-499",
                    "500-999",
                    "1000-1499",
                    "1500-4999",
                    "5000-9999",
                    "10000+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.turnover_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string",
                  "enum": [
                    "1-100k",
                    "101k-200k",
                    "201k-500k",
                    "501k-750k",
                    "751k-1M",
                    "1.1M-2M",
                    "2.1M-5M",
                    "5.1M-7.5M",
                    "7.6M-10M",
                    "11M-20M",
                    "21M-50M",
                    "51M-75M",
                    "76M-100M",
                    "100M-250M",
                    "251M-500M",
                    "501M-1B",
                    "1B+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.fleet_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string",
                  "enum": [
                    "1-2",
                    "3-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.job_level_rank"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3,
                    4,
                    5,
                    6,
                    7,
                    8,
                    9,
                    10,
                    11,
                    12,
                    13
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "email.deliverability_score"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100
                }
              }
            }
          }
        ]
      },
      "Health": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded",
              "down"
            ]
          },
          "version": {
            "type": "string",
            "description": "The API release, such as 2.0.0."
          },
          "api_version": {
            "type": "string",
            "description": "The latest MyDataHub-Version, such as 2027-01-15."
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "tps_screen": {
            "$ref": "#/components/schemas/TpsScreen"
          },
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "status_page": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "status",
          "version",
          "api_version",
          "dataset_version",
          "tps_screen",
          "time",
          "status_page"
        ],
        "description": "Whether the API is up, and which versions it serves."
      },
      "InFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "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"
            ]
          },
          "op": {
            "type": "string",
            "const": "in"
          },
          "values": {
            "minItems": 1,
            "maxItems": 10000,
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ],
              "description": "A code, a rank or a boolean, as the field's catalogue lists it."
            }
          }
        },
        "required": [
          "field",
          "op",
          "values"
        ],
        "additionalProperties": false,
        "description": "The field holds one of the listed codes.",
        "examples": [
          {
            "field": "company.sic_2007",
            "op": "in",
            "values": [
              "C"
            ]
          }
        ],
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.sic_2007"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^([A-U]|[0-9]{2,5})$"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.business_class"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.employee_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "1-5",
                      "6-9",
                      "10-19",
                      "20-49",
                      "50-99",
                      "100-199",
                      "200-349",
                      "350-499",
                      "500-999",
                      "1000-1499",
                      "1500-4999",
                      "5000-9999",
                      "10000+",
                      "unclassified"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.turnover_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "1-100k",
                      "101k-200k",
                      "201k-500k",
                      "501k-750k",
                      "751k-1M",
                      "1.1M-2M",
                      "2.1M-5M",
                      "5.1M-7.5M",
                      "7.6M-10M",
                      "11M-20M",
                      "21M-50M",
                      "51M-75M",
                      "76M-100M",
                      "100M-250M",
                      "251M-500M",
                      "501M-1B",
                      "1B+",
                      "unclassified"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.fleet_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "1-2",
                      "3-5",
                      "6-9",
                      "10-19",
                      "20-49",
                      "50-99",
                      "100+",
                      "unclassified"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.type"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.status"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.subscriber_class"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "ltd",
                      "plc",
                      "llp",
                      "scottish_partnership",
                      "public_body",
                      "charity_incorporated",
                      "sole_trader",
                      "ordinary_partnership",
                      "unknown"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.companies_house_number"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z0-9]{8}$"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "site.region"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "north_east",
                      "north_west",
                      "yorkshire_and_the_humber",
                      "east_midlands",
                      "west_midlands",
                      "east_of_england",
                      "london",
                      "south_east",
                      "south_west",
                      "scotland",
                      "wales",
                      "northern_ireland",
                      "crown_dependencies"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "site.county"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "site.town"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "site.postcode"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "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})?)?$"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.title_family"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.job_function"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.job_level_rank"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "integer",
                    "enum": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6,
                      7,
                      8,
                      9,
                      10,
                      11,
                      12,
                      13,
                      0
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.premium"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "email.exists"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "email.type"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "named",
                      "generic_local_part",
                      "generic_domain"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "phone.exists"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "phone.tps_ctps_status"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "clear",
                      "tps_registered",
                      "ctps_registered",
                      "tps_or_ctps_registered",
                      "not_screened"
                    ]
                  }
                }
              }
            }
          }
        ]
      },
      "InListFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "company.companies_house_number",
              "contact.title",
              "email.address_sha256",
              "email.domain_sha256",
              "phone.e164_sha256"
            ]
          },
          "op": {
            "type": "string",
            "const": "in_list"
          },
          "list_id": {
            "type": "string",
            "pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
            ]
          }
        },
        "required": [
          "field",
          "op",
          "list_id"
        ],
        "additionalProperties": false,
        "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.",
        "examples": [
          {
            "field": "email.address_sha256",
            "op": "in_list",
            "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
          }
        ]
      },
      "InsufficientCreditsProblem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI under https://emailmovers.com/mydatahub/docs/errors/ naming the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short summary of the problem type."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "description": "What happened on this request, in plain English."
          },
          "instance": {
            "description": "The request path or a request id this problem belongs to.",
            "type": "string"
          },
          "code": {
            "type": "string",
            "const": "insufficient-credits"
          },
          "next_step": {
            "type": "string",
            "description": "What to do next, in plain English."
          },
          "did_you_mean": {
            "description": "The closest valid values, best first.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "description": "For validation-failed: every problem found, each with a JSON pointer.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProblemError"
            }
          },
          "required_scope": {
            "description": "For insufficient-scope: the scope to request, such as orders:write.",
            "type": "string"
          },
          "retry_after_seconds": {
            "description": "For rate-limited and service-unavailable: the same value as the Retry-After header.",
            "type": "integer",
            "minimum": 0
          },
          "quote_id": {
            "description": "The machine quote to retry after topping up; absent for an enrichment.",
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "quote": {
            "description": "The machine quote the balance does not cover; absent for an enrichment.",
            "$ref": "#/components/schemas/MachineQuote"
          },
          "credits_required": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "credits_available": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "top_up_url": {
            "type": "string",
            "format": "uri",
            "description": "Stripe Checkout on mydatahub.emailmovers.com. Money never moves inside an agent host."
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "next_step",
          "credits_required",
          "credits_available",
          "top_up_url"
        ],
        "description": "402: the balance does not cover the machine quote (or the enrichment), which is carried here with a Stripe Checkout top_up_url. Nothing was charged."
      },
      "JurisdictionExclusion": {
        "type": "object",
        "properties": {
          "jurisdiction": {
            "type": "string",
            "description": "An ISO 3166 code, such as DE, CA or US-CA."
          },
          "removed": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "jurisdiction",
          "removed"
        ],
        "description": "Records one policy removed."
      },
      "LevelCount": {
        "type": "object",
        "properties": {
          "level": {
            "type": "string"
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          }
        },
        "required": [
          "level",
          "contacts"
        ],
        "description": "Contacts at one job level."
      },
      "LiaDocument": {
        "type": "object",
        "properties": {
          "ref": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "published_at": {
            "type": "string",
            "format": "date"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ]
          },
          "summary": {
            "type": "string"
          },
          "versions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ref": {
                  "type": "string"
                },
                "published_at": {
                  "type": "string",
                  "format": "date"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "required": [
                "ref",
                "published_at",
                "url"
              ]
            }
          }
        },
        "required": [
          "ref",
          "version",
          "published_at",
          "url",
          "lawful_basis",
          "summary",
          "versions"
        ],
        "description": "The published legitimate interests assessment with its version history."
      },
      "Licence": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "multi_use_12m",
              "outright"
            ],
            "description": "multi_use_12m (12 month multi-use, every plan) or outright (1.8 credits a record, proposed)."
          },
          "reuse_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "Order date plus 12 months; null for outright."
          },
          "resale_prohibited": {
            "type": "boolean"
          },
          "permitted_channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "email",
                "telephone",
                "post"
              ]
            },
            "description": "email, telephone and post on standard terms."
          },
          "warranty_url": {
            "type": "string",
            "format": "uri"
          },
          "terms_version": {
            "type": "string",
            "description": "The version of the Data Licence and Sharing Agreement the licence is under, such as 1.0."
          },
          "terms_url": {
            "description": "Where that version of the Data Licence and Sharing Agreement is published.",
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "type",
          "reuse_until",
          "resale_prohibited",
          "permitted_channels",
          "warranty_url",
          "terms_version"
        ],
        "description": "Licence terms as data, on every quote, order, records page and receipt. Records stay usable, pushable and re-downloadable free until reuse_until."
      },
      "LicenceTerms": {
        "type": "object",
        "properties": {
          "licence_type": {
            "type": "string",
            "enum": [
              "multi_use_12m",
              "outright"
            ],
            "description": "multi_use_12m (12 month multi-use, every plan) or outright (1.8 credits a record, proposed)."
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed"
            ]
          },
          "credits_per_record": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "permitted_channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "email",
                "telephone",
                "post"
              ]
            }
          },
          "reuse_months": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "12 for multi_use_12m; null for outright."
          },
          "resale_prohibited": {
            "type": "boolean"
          },
          "warranty_url": {
            "type": "string",
            "format": "uri"
          },
          "terms_version": {
            "type": "string"
          }
        },
        "required": [
          "licence_type",
          "status",
          "credits_per_record",
          "permitted_channels",
          "reuse_months",
          "resale_prohibited",
          "warranty_url",
          "terms_version"
        ],
        "description": "Licence terms for a plan, as in licence.json."
      },
      "LocationCandidate": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "region",
              "county",
              "town",
              "local_authority",
              "postcode_area",
              "postcode_district",
              "postcode_sector",
              "postcode_unit",
              "geography_set",
              "radius"
            ]
          },
          "code": {
            "type": "string",
            "description": "The filter code, or the ONS code for a centre."
          },
          "label": {
            "type": "string"
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          },
          "centre": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "number"
                  },
                  "lon": {
                    "type": "number"
                  }
                },
                "required": [
                  "lat",
                  "lon"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "filter": {
            "description": "A ready filter for this candidate.",
            "$ref": "#/components/schemas/Filter",
            "discriminator": {
              "propertyName": "op",
              "mapping": {
                "in": "#/components/schemas/InFilter",
                "between": "#/components/schemas/BetweenFilter",
                "gte": "#/components/schemas/GteFilter",
                "lte": "#/components/schemas/LteFilter",
                "matches": "#/components/schemas/MatchesFilter",
                "within_radius": "#/components/schemas/WithinRadiusFilter",
                "in_list": "#/components/schemas/InListFilter",
                "since": "#/components/schemas/SinceFilter"
              }
            }
          }
        },
        "required": [
          "kind",
          "code",
          "label",
          "contacts",
          "centre",
          "filter"
        ],
        "description": "One reading of the text."
      },
      "LocationRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Free text such as \"20 miles of Leeds\", \"Yorkshire\" or \"SW1\"."
          },
          "radius_miles": {
            "type": "number",
            "minimum": 1,
            "maximum": 100
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false,
        "description": "A place to resolve into geography filters."
      },
      "LocationResolution": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "ambiguous": {
            "type": "boolean",
            "description": "True when more than one candidate fits; ask the person which they meant."
          },
          "question": {
            "type": [
              "string",
              "null"
            ]
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LocationCandidate"
            }
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          }
        },
        "required": [
          "text",
          "ambiguous",
          "question",
          "candidates",
          "disclosure"
        ],
        "description": "Candidates for a place. Ambiguous names come back as candidates, never a silent choice."
      },
      "LteFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "company.employee_band",
              "company.turnover_band",
              "company.fleet_band",
              "contact.job_level_rank",
              "contact.company_contact_rank",
              "email.deliverability_score"
            ]
          },
          "op": {
            "type": "string",
            "const": "lte"
          },
          "value": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              {
                "type": "number"
              }
            ],
            "description": "A band code or a number from the field's order."
          }
        },
        "required": [
          "field",
          "op",
          "value"
        ],
        "additionalProperties": false,
        "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.",
        "examples": [
          {
            "field": "contact.job_level_rank",
            "op": "lte",
            "value": 6
          }
        ],
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.employee_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string",
                  "enum": [
                    "1-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100-199",
                    "200-349",
                    "350-499",
                    "500-999",
                    "1000-1499",
                    "1500-4999",
                    "5000-9999",
                    "10000+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.turnover_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string",
                  "enum": [
                    "1-100k",
                    "101k-200k",
                    "201k-500k",
                    "501k-750k",
                    "751k-1M",
                    "1.1M-2M",
                    "2.1M-5M",
                    "5.1M-7.5M",
                    "7.6M-10M",
                    "11M-20M",
                    "21M-50M",
                    "51M-75M",
                    "76M-100M",
                    "100M-250M",
                    "251M-500M",
                    "501M-1B",
                    "1B+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "company.fleet_band"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string",
                  "enum": [
                    "1-2",
                    "3-5",
                    "6-9",
                    "10-19",
                    "20-49",
                    "50-99",
                    "100+"
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.job_level_rank"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "integer",
                  "enum": [
                    1,
                    2,
                    3,
                    4,
                    5,
                    6,
                    7,
                    8,
                    9,
                    10,
                    11,
                    12,
                    13
                  ]
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.company_contact_rank"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 1000
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "email.deliverability_score"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100
                }
              }
            }
          }
        ]
      },
      "MachineQuote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a quote id: qte_ followed by a 26 character ULID in upper case Crockford base32, such as qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3.",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "kind": {
            "type": "string",
            "const": "machine"
          },
          "organisation_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^org_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: an organisation id: org_ followed by a 26 character ULID in upper case Crockford base32, such as org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8.",
                "examples": [
                  "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The organisation the quote belongs to; create_order settles it only there. null for a quote made without an account, which the first organisation to confirm it takes."
          },
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "The count the quote was priced from.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "field_set": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
          },
          "records": {
            "type": "integer",
            "minimum": 0,
            "description": "Records after overlap and suppression; what you would receive."
          },
          "removed": {
            "type": "object",
            "properties": {
              "already_held": {
                "type": "integer",
                "minimum": 0
              },
              "suppressed": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "already_held",
              "suppressed"
            ],
            "description": "Records left out and never charged."
          },
          "credits_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "1 for a complete UK record; 1.8 outright (proposed)."
          },
          "credits_required": {
            "type": "number",
            "minimum": 0,
            "description": "records times credits_per_record (creditsFor)."
          },
          "credits_available": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Your balance; null when signed out."
          },
          "balance_after": {
            "description": "credits_available less credits_required; negative means a top-up is needed; null when signed out.",
            "type": [
              "number",
              "null"
            ]
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "What credits_required cost bought the cheapest way, at the per-contact scale or with credit packs, excluding VAT. The same for every caller; purchase says what this caller needs to buy."
          },
          "purchase": {
            "$ref": "#/components/schemas/Purchase"
          },
          "licence": {
            "$ref": "#/components/schemas/Licence"
          },
          "warranty": {
            "$ref": "#/components/schemas/Warranty"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "24 hours after creation."
          },
          "blockers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuoteBlocker"
            }
          },
          "signature": {
            "$ref": "#/components/schemas/QuoteSignature"
          }
        },
        "required": [
          "id",
          "kind",
          "organisation_id",
          "count_id",
          "dataset_version",
          "records",
          "removed",
          "credits_per_record",
          "credits_required",
          "credits_available",
          "balance_after",
          "gbp_ex_vat",
          "purchase",
          "licence",
          "warranty",
          "expires_at",
          "blockers",
          "signature"
        ],
        "description": "A machine quote: a signed price, valid 24 hours, bound to a dataset version and an organisation. create_order needs its id plus a human confirmation or a pre-authorised agent key; a confirmed flag set by a model is never consent."
      },
      "MatchesFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "contact.title"
            ]
          },
          "op": {
            "type": "string",
            "const": "matches"
          },
          "terms": {
            "minItems": 1,
            "maxItems": 500,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "mode": {
            "type": "string",
            "enum": [
              "contains",
              "starts_with",
              "exact"
            ],
            "description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
          },
          "expand": {
            "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,
            "maxItems": 5,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "plural_singular",
                "department_synonyms",
                "ampersand_and",
                "abbreviations",
                "permutations"
              ]
            }
          },
          "exclude_terms": {
            "description": "Expanded terms removed by hand. Kept in the definition so the count stays reproducible when the title dictionary changes.",
            "maxItems": 500,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        },
        "required": [
          "field",
          "op",
          "terms"
        ],
        "additionalProperties": false,
        "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.",
        "examples": [
          {
            "field": "contact.title",
            "op": "matches",
            "terms": [
              "marketing manager"
            ],
            "mode": "contains",
            "expand": [
              "plural_singular",
              "department_synonyms",
              "ampersand_and",
              "abbreviations"
            ]
          }
        ],
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "mode": {
                  "const": "exact"
                }
              },
              "required": [
                "mode"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "expand": {
                  "type": "array",
                  "maxItems": 0
                },
                "exclude_terms": {
                  "type": "array",
                  "maxItems": 0
                }
              }
            }
          }
        ]
      },
      "Meter": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "What is metered, such as record or enrich_contact."
          },
          "unit": {
            "type": "string",
            "enum": [
              "record",
              "match",
              "call"
            ]
          },
          "credits": {
            "type": "number",
            "minimum": 0,
            "description": "Credits per unit."
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed",
              "to_confirm"
            ],
            "description": "confirmed is in force; proposed awaits a decision; to_confirm is a figure still being checked."
          }
        },
        "required": [
          "action",
          "unit",
          "credits",
          "status"
        ],
        "description": "One metered action and its price in credits."
      },
      "NotGroup": {
        "type": "object",
        "properties": {
          "not": {
            "$ref": "#/components/schemas/WhereNode"
          }
        },
        "required": [
          "not"
        ],
        "additionalProperties": false,
        "description": "Negation: the single node inside must not match."
      },
      "NoticeVersion": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string"
          },
          "published_at": {
            "type": "string",
            "format": "date"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "version",
          "published_at",
          "url"
        ],
        "description": "One dated version of the notice."
      },
      "Objection": {
        "type": "object",
        "properties": {
          "suppression_id": {
            "type": "string",
            "pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "The list the record now sits on.",
            "examples": [
              "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "record_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
                "examples": [
                  "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "licensee",
              "emailmovers"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "suppressed",
              "pending"
            ],
            "description": "suppressed now, or pending until the database-wide overlay applies."
          },
          "suppressed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "effective_by": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "suppression_id",
          "record_id",
          "scope",
          "status",
          "suppressed_at",
          "effective_by"
        ],
        "description": "The suppression an objection created. Database-wide objections reach every licensee holding the record through the suppression.created webhook."
      },
      "ObjectionRequest": {
        "type": "object",
        "properties": {
          "record_id": {
            "type": "string",
            "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
            "examples": [
              "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "email_sha256": {
            "description": "SHA-256 of the trimmed, lower cased address, when the record id is not known.",
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "telephone",
              "post",
              "web_form",
              "other"
            ]
          },
          "received_at": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 date and time, with Z or an offset such as +01:00."
          },
          "scope": {
            "type": "string",
            "enum": [
              "licensee",
              "emailmovers"
            ],
            "description": "licensee suppresses the record for your organisation at once; emailmovers suppresses it database-wide within one working day."
          },
          "note": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "channel",
          "received_at",
          "scope"
        ],
        "additionalProperties": false,
        "description": "An objection to direct marketing, to record and propagate: exactly one of record_id or email_sha256.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "record_id": true
            },
            "required": [
              "record_id"
            ]
          },
          {
            "type": "object",
            "properties": {
              "email_sha256": true
            },
            "required": [
              "email_sha256"
            ]
          }
        ]
      },
      "OpenApiDocument": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {},
        "description": "This OpenAPI 3.1 document, with x-cost-credits on every operation."
      },
      "OperatorInfo": {
        "type": "object",
        "properties": {
          "op": {
            "type": "string",
            "enum": [
              "in",
              "between",
              "gte",
              "lte",
              "matches",
              "within_radius",
              "in_list",
              "since",
              "all",
              "any",
              "not"
            ]
          },
          "applies_to": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "op",
          "applies_to",
          "description"
        ],
        "description": "An operator of the audience definition."
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "examples": [
              "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "building",
              "verifying",
              "ready",
              "failed",
              "cancelled"
            ],
            "description": "queued, building, verifying, ready; failed if processing failed; cancelled (only while queued)."
          },
          "name": {
            "type": "string"
          },
          "quote_id": {
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "The machine quote the order settled.",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "The count the machine quote was priced from.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "field_set": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
          },
          "delivery": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "api",
                "csv",
                "google_sheets"
              ]
            }
          },
          "records": {
            "type": "integer",
            "minimum": 0
          },
          "credits_charged": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "credits_remaining": {
            "type": "number",
            "minimum": 0,
            "description": "The balance right after this order was charged."
          },
          "cost_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "The charge in GBP excluding VAT at your plan's rate."
          },
          "licence_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the licence ends; null for outright ownership."
          },
          "licence": {
            "$ref": "#/components/schemas/Licence"
          },
          "confirmed_by": {
            "$ref": "#/components/schemas/ConfirmedBy"
          },
          "verification": {
            "description": "The real-time check at delivery, such as 4,102 checked, 4,071 passed.",
            "type": "object",
            "properties": {
              "checked": {
                "type": "integer",
                "minimum": 0
              },
              "passed": {
                "type": "integer",
                "minimum": 0
              },
              "replaced": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "checked",
              "passed",
              "replaced"
            ]
          },
          "records_url": {
            "type": "string",
            "pattern": "^\\/v1\\/[A-Za-z0-9_\\-./]+$",
            "format": "uri-reference",
            "description": "A path on https://mydatahub.emailmovers.com starting /v1/. Resolve it against the origin (RFC 3986), not by appending it to the server URL."
          },
          "download_url": {
            "description": "302 to a single-use signed URL that lives 5 minutes.",
            "type": "string",
            "pattern": "^\\/v1\\/[A-Za-z0-9_\\-./]+$",
            "format": "uri-reference"
          },
          "receipt_url": {
            "type": "string",
            "pattern": "^\\/v1\\/[A-Za-z0-9_\\-./]+$",
            "format": "uri-reference",
            "description": "A path on https://mydatahub.emailmovers.com starting /v1/. Resolve it against the origin (RFC 3986), not by appending it to the server URL."
          },
          "validation_report": {
            "description": "Present once the order is ready.",
            "$ref": "#/components/schemas/ValidationReportLinks"
          },
          "buyer_kit": {
            "$ref": "#/components/schemas/BuyerKit"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "ready_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "failure": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "status",
          "quote_id",
          "count_id",
          "records",
          "credits_charged",
          "credits_remaining",
          "cost_gbp",
          "licence_expires_at",
          "licence",
          "confirmed_by",
          "records_url"
        ],
        "description": "The purchase and its delivery: status, records, charges, the licence, links to records, download, the validation report and the signed compliance receipt."
      },
      "OrderFailedEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "order.failed"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "type": "object",
            "properties": {
              "order_id": {
                "type": "string",
                "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
                "examples": [
                  "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
                ]
              },
              "reason": {
                "type": "string"
              },
              "credits_refunded": {
                "type": "number",
                "minimum": 0,
                "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
              }
            },
            "required": [
              "order_id",
              "reason",
              "credits_refunded"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "Processing failed; credits are refunded."
      },
      "OrderList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of orders, newest first."
      },
      "OrderReadyEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "order.ready"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "type": "object",
            "properties": {
              "order_id": {
                "type": "string",
                "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
                "examples": [
                  "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
                ]
              },
              "records": {
                "type": "integer",
                "minimum": 0
              },
              "records_url": {
                "type": "string",
                "pattern": "^\\/v1\\/[A-Za-z0-9_\\-./]+$",
                "format": "uri-reference",
                "description": "A path on https://mydatahub.emailmovers.com starting /v1/. Resolve it against the origin (RFC 3986), not by appending it to the server URL."
              },
              "receipt_url": {
                "type": "string",
                "pattern": "^\\/v1\\/[A-Za-z0-9_\\-./]+$",
                "format": "uri-reference",
                "description": "A path on https://mydatahub.emailmovers.com starting /v1/. Resolve it against the origin (RFC 3986), not by appending it to the server URL."
              }
            },
            "required": [
              "order_id",
              "records",
              "records_url",
              "receipt_url"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "Records are available."
      },
      "OrderRequest": {
        "type": "object",
        "properties": {
          "quote_id": {
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "A live machine quote from quote_order. Without one nothing is charged.",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "delivery": {
            "description": "api (fetch records), csv (signed download) and google_sheets. Default api.",
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "api",
                "csv",
                "google_sheets"
              ]
            }
          },
          "confirmation_token": {
            "type": "string",
            "minLength": 16,
            "maxLength": 2000,
            "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."
          },
          "licence_accepted_version": {
            "description": "The version of the Data Licence and Sharing Agreement the person accepted for this order: the version in force, the account's agreements.dlsa.version. Required when a person orders in the app; an agent key carries the acceptance made with it, and a confirmation_token the one made on the approval page.",
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "quote_id"
        ],
        "additionalProperties": false,
        "description": "Spend credits against a machine quote. A model-set confirmed flag is never consent: the order needs a human confirmation (MCP elicitation or confirmation_token) or a pre-authorised agent key within its limits."
      },
      "OtherBadge": {
        "type": "object",
        "properties": {
          "badge": {
            "type": "string",
            "enum": [
              "re_checking",
              "unverified",
              "suppressed"
            ]
          },
          "date": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "The date behind the badge, if any."
          },
          "label": {
            "type": "string",
            "description": "Such as Verified 12 September 2026."
          }
        },
        "required": [
          "badge",
          "date",
          "label"
        ],
        "description": "Re-checking, unverified or suppressed."
      },
      "OtherBucket": {
        "type": "object",
        "properties": {
          "cells": {
            "type": "integer",
            "minimum": 0,
            "description": "How many cells were folded into other."
          },
          "contacts": {
            "$ref": "#/components/schemas/CellCount"
          },
          "companies": {
            "$ref": "#/components/schemas/CellCount"
          }
        },
        "required": [
          "cells",
          "contacts"
        ],
        "description": "Every cell beyond the top 50, summed."
      },
      "Overlap": {
        "type": "object",
        "properties": {
          "connection_id": {
            "type": "string",
            "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
            "examples": [
              "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
            ]
          },
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "records": {
            "type": "integer",
            "minimum": 0
          },
          "already_held": {
            "type": "integer",
            "minimum": 0,
            "description": "Records already in the CRM; never charged."
          },
          "new_to_you": {
            "type": "integer",
            "minimum": 0
          },
          "method": {
            "type": "string",
            "const": "salted_sha256_in_memory"
          },
          "retained": {
            "type": "boolean",
            "const": false,
            "description": "Nothing from the CRM is kept after the check."
          },
          "checked_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "connection_id",
          "count_id",
          "records",
          "already_held",
          "new_to_you",
          "method",
          "retained",
          "checked_at"
        ],
        "description": "The New to you overlap check: salted SHA-256 email matching in memory, nothing retained."
      },
      "OverlapRequest": {
        "type": "object",
        "properties": {
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Za-z2-7]{20}$",
            "description": "A count id from POST /v1/counts or count_audience. Either case is accepted; responses use upper case.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "quote_id": {
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a quote id: qte_ followed by a 26 character ULID in upper case Crockford base32, such as qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3.",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          }
        },
        "additionalProperties": false,
        "description": "The count or the machine quote to compare with the CRM: exactly one of count_id or quote_id.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "count_id": true
            },
            "required": [
              "count_id"
            ]
          },
          {
            "type": "object",
            "properties": {
              "quote_id": true
            },
            "required": [
              "quote_id"
            ]
          }
        ]
      },
      "PaymentReceipt": {
        "type": "object",
        "properties": {
          "number": {
            "type": "string",
            "description": "The receipt number, such as MDH-000042: one sequence for every receipt, with no number skipped."
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "supplier": {
            "type": "object",
            "properties": {
              "name": {
                "description": "The company, such as Emailmovers Limited.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "company_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "registered_office": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "vat_number": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "company_number",
              "registered_office",
              "vat_number"
            ],
            "description": "Who sold the credits, as the server's settings name them when the receipt is written. In production a receipt is never written without them; a development server may leave them null."
          },
          "customer": {
            "type": "object",
            "properties": {
              "organisation_id": {
                "type": "string",
                "pattern": "^org_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: an organisation id: org_ followed by a 26 character ULID in upper case Crockford base32, such as org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8.",
                "examples": [
                  "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8"
                ]
              },
              "organisation_name": {
                "type": "string"
              },
              "business_name": {
                "description": "The organisation's business name when the receipt was written, which the receipt leads with: confirmed by an owner for an account made by self-serve sign-up, or the name Emailmovers set the account up under. Null while a self-serve account has not confirmed it, and on receipts written before 21 October 2026.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "description": "The name on the billing details Checkout collected: the business name when the buyer gave one.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "address": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/BillingAddress"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "vat_number": {
                "description": "The buyer's own VAT number, when they gave one at checkout.",
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "organisation_id",
              "organisation_name",
              "business_name",
              "name",
              "address",
              "vat_number"
            ],
            "description": "Who bought the credits, as Stripe Checkout collected it."
          },
          "description": {
            "type": "string",
            "description": "What was bought, such as 1 credit pack of 40,000."
          },
          "credits": {
            "type": "integer",
            "minimum": 0
          },
          "gbp_per_credit": {
            "type": "number",
            "minimum": 0,
            "description": "The unit price: one credit, excluding VAT, to six decimal places."
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "vat_rate_percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "vat_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling, to two decimal places."
          },
          "total_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "What the card was charged, VAT included."
          },
          "paid_by": {
            "type": "string",
            "const": "card",
            "description": "Card, through Stripe Checkout."
          },
          "payment_reference": {
            "type": "string",
            "description": "Stripe's reference for the payment."
          },
          "refunds": {
            "type": "string",
            "description": "The refund terms the purchase was made under."
          },
          "test_mode": {
            "type": "boolean",
            "description": "A Stripe test mode payment: no money moved."
          }
        },
        "required": [
          "number",
          "issued_at",
          "supplier",
          "customer",
          "description",
          "credits",
          "gbp_per_credit",
          "gbp_ex_vat",
          "vat_rate_percent",
          "vat_gbp",
          "total_gbp",
          "paid_by",
          "payment_reference",
          "refunds",
          "test_mode"
        ],
        "description": "The receipt for a paid credit purchase, which serves as the VAT invoice: the supplier and its VAT number, the buyer's name, billing address and VAT number when given, what was bought, the price per credit and in total excluding VAT, the VAT rate and amount, and the total. Written once, when the credits are added."
      },
      "PlaceCentre": {
        "type": "object",
        "properties": {
          "place": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "A place name, resolved with resolve_location, such as Leeds."
          },
          "code": {
            "description": "The ONS geography code of the chosen candidate when resolve_location found more than one, such as E08000035 for the Leeds district.",
            "type": "string",
            "minLength": 1,
            "maxLength": 20
          }
        },
        "required": [
          "place"
        ],
        "additionalProperties": false,
        "description": "A named place. Ambiguous names come back from resolve_location as candidates, never a silent choice."
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "Such as free, pay_as_you_go or plan_12_month."
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "free",
              "subscription",
              "pack"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed",
              "to_confirm"
            ],
            "description": "confirmed is in force; proposed awaits a decision; to_confirm is a figure still being checked."
          },
          "available_to": {
            "type": "string",
            "enum": [
              "everyone",
              "new_customers",
              "existing_customers"
            ],
            "description": "everyone; new_customers only (the subscription); existing_customers only, who keep their prices (pay as you go and the 12-month plan)."
          },
          "price_gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "billing_period": {
            "type": "string",
            "enum": [
              "once",
              "month",
              "year"
            ]
          },
          "contract_months": {
            "description": "The contract's length in months, such as 12; absent when there is none.",
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "annual_price_gbp_ex_vat": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "description": "Pounds sterling excluding VAT, to two decimal places."
              },
              {
                "type": "null"
              }
            ]
          },
          "credits": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits per billing period, or once."
          },
          "per_record_gbp": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "description": "Pounds sterling excluding VAT, to two decimal places."
              },
              {
                "type": "null"
              }
            ],
            "description": "Price per record at full use of the allowance; null for the free plan."
          },
          "rollover_cap_credits": {
            "description": "Subscription credits roll over while subscribed, up to this many; 0 when each period's credits are used or lost.",
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "credits_expire": {
            "type": "boolean"
          },
          "for_whom": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "status",
          "available_to",
          "price_gbp_ex_vat",
          "billing_period",
          "credits",
          "per_record_gbp",
          "credits_expire",
          "for_whom"
        ],
        "description": "A plan: free, a rolling subscription or a credit pack. No seats on any plan."
      },
      "PointCentre": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": 49,
            "maximum": 61
          },
          "lon": {
            "type": "number",
            "minimum": -9,
            "maximum": 2
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false,
        "description": "A latitude and longitude in WGS84 degrees."
      },
      "PostcodeCentre": {
        "type": "object",
        "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."
          }
        },
        "required": [
          "postcode"
        ],
        "additionalProperties": false,
        "description": "A postcode centroid from ONSPD."
      },
      "Preview": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^prv_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a preview id: prv_ followed by a 26 character ULID in upper case Crockford base32, such as prv_01JB4H3M7Q2V7XN3M9R6T1Y5W8.",
            "examples": [
              "prv_01JB4H3M7Q2V7XN3M9R6T1Y5W8"
            ]
          },
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "seed": {
            "type": "string",
            "description": "The seed the rows came from; the same audience gives the same seed."
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "The count the rows were drawn from, rounded as disclosure says."
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          },
          "rows": {
            "maxItems": 25,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreviewRow"
            }
          },
          "withheld": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "rows": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "reason": {
                    "type": "string"
                  }
                },
                "required": [
                  "rows",
                  "reason"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Rows held back: all of them when the count is under 25, or rows whose title fewer than 10 people hold."
          },
          "masked": {
            "type": "boolean",
            "const": true
          },
          "watermark": {
            "description": "The account id watermarked into sample CSVs; null when signed out.",
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "count_id",
          "dataset_version",
          "seed",
          "count",
          "disclosure",
          "rows",
          "withheld",
          "masked",
          "watermark",
          "created_at"
        ],
        "description": "A free, masked sample of up to 25 rows. Repeating a sample returns the same rows."
      },
      "PreviewRequest": {
        "type": "object",
        "properties": {
          "audience": {
            "$ref": "#/components/schemas/AudienceRef"
          },
          "count_id": {
            "description": "A count id instead of an audience.",
            "type": "string",
            "pattern": "^cnt_[A-Za-z2-7]{20}$",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "limit": {
            "description": "Rows to return, 1 to 25. Default 10.",
            "default": 10,
            "type": "integer",
            "minimum": 1,
            "maximum": 25
          },
          "shuffle": {
            "description": "Draw a new seed. Counts against your rate budget and is logged. Default false, so a repeat returns the same rows.",
            "default": false,
            "type": "boolean"
          }
        },
        "additionalProperties": false,
        "description": "The audience or count to sample: exactly one of audience or count_id.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "audience": true
            },
            "required": [
              "audience"
            ]
          },
          {
            "type": "object",
            "properties": {
              "count_id": true
            },
            "required": [
              "count_id"
            ]
          }
        ]
      },
      "PreviewRow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^prv_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "A session-scoped id standing in for the record. It never reveals contact_ ids.",
            "examples": [
              "prv_01JB4H3M7Q2V7XN3M9R6T1Y5W8"
            ]
          },
          "title": {
            "type": "string"
          },
          "job_level": {
            "description": "The level, such as Director; null when the level is not known.",
            "type": [
              "string",
              "null"
            ]
          },
          "job_function": {
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "companies_house_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": "string"
              },
              "employee_band": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sic_2007": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "name",
              "companies_house_number",
              "status",
              "employee_band",
              "sic_2007"
            ]
          },
          "site": {
            "type": "object",
            "properties": {
              "town": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "postcode_district": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "region": {
                "type": "string"
              }
            },
            "required": [
              "town",
              "postcode_district",
              "region"
            ]
          },
          "email_masked": {
            "description": "First character of the local part plus the top level domain, such as j••••@••••.co.uk.",
            "type": [
              "string",
              "null"
            ]
          },
          "email_type": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "named",
                  "generic_local_part",
                  "generic_domain"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "phone_masked": {
            "description": "To the area code, such as 0113 ••• •••1.",
            "type": [
              "string",
              "null"
            ]
          },
          "tps_ctps_status": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "clear",
                  "tps_registered",
                  "ctps_registered",
                  "tps_or_ctps_registered",
                  "not_screened"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "badges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VerificationBadge"
            }
          },
          "why_it_matches": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WhyItMatches"
            }
          },
          "provenance": {
            "$ref": "#/components/schemas/ProvenanceCard"
          },
          "compliance": {
            "$ref": "#/components/schemas/ComplianceObject"
          }
        },
        "required": [
          "id",
          "title",
          "job_level",
          "job_function",
          "company",
          "site",
          "email_masked",
          "email_type",
          "phone_masked",
          "tps_ctps_status",
          "badges",
          "why_it_matches",
          "provenance",
          "compliance"
        ],
        "description": "One masked sample record."
      },
      "PriceBand": {
        "type": "object",
        "properties": {
          "from_records": {
            "type": "integer",
            "minimum": 0
          },
          "to_records": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "null for the last band."
          },
          "gbp_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          }
        },
        "required": [
          "from_records",
          "to_records",
          "gbp_per_record"
        ],
        "description": "One band of the per-contact scale."
      },
      "PriceEstimate": {
        "type": "object",
        "properties": {
          "credits": {
            "type": "number",
            "minimum": 0,
            "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
          },
          "gbp_ex_vat": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
            },
            "additionalProperties": {
              "type": "number",
              "minimum": 0,
              "description": "Pounds sterling excluding VAT, to two decimal places."
            },
            "description": "The price in GBP excluding VAT: per_contact_scale (every credit at the scale) and cheapest (the cheapest real purchase, at the scale or with credit packs)."
          }
        },
        "required": [
          "credits",
          "gbp_ex_vat"
        ],
        "description": "What ordering the whole count would cost. An estimate; quote_order gives the machine quote."
      },
      "PriceScale": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "const": "per_contact_scale"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "proposed",
              "to_confirm"
            ],
            "description": "confirmed is in force; proposed awaits a decision; to_confirm is a figure still being checked."
          },
          "available_to": {
            "type": "string",
            "enum": [
              "everyone",
              "new_customers",
              "existing_customers"
            ],
            "description": "everyone; new_customers only (the subscription); existing_customers only, who keep their prices (pay as you go and the 12-month plan)."
          },
          "minimum_order_records": {
            "type": "integer",
            "minimum": 0
          },
          "rule": {
            "type": "string",
            "description": "How a purchase is priced, in words."
          },
          "bands": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PriceBand"
            }
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "available_to",
          "minimum_order_records",
          "rule",
          "bands"
        ],
        "description": "The per-contact scale: 1 credit buys 1 record at the rate of the band the purchase falls in. A quote's purchase options compare it with the credit pack and lead with the cheapest."
      },
      "Pricing": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string"
          },
          "valid_from": {
            "type": "string",
            "format": "date"
          },
          "currency": {
            "type": "string",
            "const": "GBP"
          },
          "vat_treatment": {
            "type": "string"
          },
          "credit_definition": {
            "type": "string"
          },
          "price_scale": {
            "$ref": "#/components/schemas/PriceScale"
          },
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plan"
            }
          },
          "credit_packs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditPack"
            }
          },
          "credit_rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditRule"
            }
          },
          "licence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LicenceTerms"
            }
          },
          "guarantee": {
            "type": "object",
            "properties": {
              "current": {
                "$ref": "#/components/schemas/Warranty"
              },
              "proposed": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Warranty"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "refunds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "current",
              "proposed",
              "refunds"
            ]
          },
          "trial": {
            "type": "object",
            "properties": {
              "credits": {
                "type": "integer",
                "minimum": 0
              },
              "card_required": {
                "type": "boolean"
              },
              "expires": {
                "type": "boolean"
              }
            },
            "required": [
              "credits",
              "card_required",
              "expires"
            ]
          },
          "promises": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PricingPromise"
            }
          },
          "meters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Meter"
            },
            "description": "What agents and code are metered on, in credits, the same on every surface."
          },
          "action_path": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActionPathStep"
            },
            "description": "How to buy: quote_order for a machine quote, create_order with a confirmation, and the top-up page when the balance is short."
          }
        },
        "required": [
          "version",
          "valid_from",
          "currency",
          "vat_treatment",
          "credit_definition",
          "price_scale",
          "plans",
          "credit_packs",
          "credit_rules",
          "licence",
          "guarantee",
          "trial",
          "promises",
          "meters",
          "action_path"
        ],
        "description": "The per-contact scale, plans, credit packs, credit rules, licence terms, the guarantee and the promises, in GBP excluding VAT. The same content as https://mydatahub.emailmovers.com/pricing.json."
      },
      "PricingPromise": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
          },
          "statement": {
            "type": "string"
          },
          "in_practice": {
            "type": "string"
          }
        },
        "required": [
          "key",
          "statement",
          "in_practice"
        ],
        "description": "One of the seven promises on the pricing page."
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI under https://emailmovers.com/mydatahub/docs/errors/ naming the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short summary of the problem type."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "description": "What happened on this request, in plain English."
          },
          "instance": {
            "description": "The request path or a request id this problem belongs to.",
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid-request",
              "idempotency-key-required",
              "unsupported-version",
              "authentication-required",
              "account-required",
              "insufficient-credits",
              "insufficient-scope",
              "confirmation-required",
              "business-details-required",
              "licence-acceptance-required",
              "dpa-acceptance-required",
              "agent-budget-exceeded",
              "not-found",
              "method-not-allowed",
              "idempotency-key-reused",
              "quote-expired",
              "order-not-ready",
              "order-not-cancellable",
              "validation-failed",
              "quote-required",
              "dataset-unavailable",
              "rate-limited",
              "internal-error",
              "not-implemented",
              "service-unavailable",
              "tps-screen-expired"
            ],
            "description": "The problem type as a stable code."
          },
          "next_step": {
            "type": "string",
            "description": "What to do next, in plain English."
          },
          "did_you_mean": {
            "description": "The closest valid values, best first.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "description": "For validation-failed: every problem found, each with a JSON pointer.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProblemError"
            }
          },
          "required_scope": {
            "description": "For insufficient-scope: the scope to request, such as orders:write.",
            "type": "string"
          },
          "retry_after_seconds": {
            "description": "For rate-limited and service-unavailable: the same value as the Retry-After header.",
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "next_step"
        ],
        "description": "An RFC 9457 problem. MCP tool errors carry the same object with isError true.",
        "examples": [
          {
            "type": "https://emailmovers.com/mydatahub/docs/errors/validation-failed",
            "title": "The request is not valid",
            "status": 422,
            "detail": "Unknown field company.employees.",
            "instance": "/v1/counts",
            "code": "validation-failed",
            "next_step": "Fix each entry in errors, using did_you_mean where given, and send it again.",
            "errors": [
              {
                "pointer": "/audience/where/all/0/field",
                "code": "invalid_value",
                "message": "Unknown field company.employees.",
                "did_you_mean": [
                  "company.employee_band"
                ]
              }
            ]
          }
        ]
      },
      "ProblemError": {
        "type": "object",
        "properties": {
          "pointer": {
            "type": "string",
            "description": "RFC 6901 JSON pointer to the member at fault, such as /audience/where/all/0/field."
          },
          "code": {
            "type": "string",
            "description": "What went wrong, such as invalid_value or custom."
          },
          "message": {
            "type": "string"
          },
          "did_you_mean": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "pointer",
          "code",
          "message"
        ],
        "description": "One validation failure."
      },
      "Provenance": {
        "type": "object",
        "properties": {
          "company": {
            "type": "object",
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "emailmovers_research",
                  "companies_house",
                  "onspd",
                  "ukbizdirectory",
                  "partner_rampedup"
                ]
              },
              "as_of": {
                "type": "string",
                "format": "date"
              }
            },
            "required": [
              "source",
              "as_of"
            ],
            "description": "Where the company facts came from and the snapshot date."
          },
          "contact": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "emailmovers_research",
                      "companies_house",
                      "onspd",
                      "ukbizdirectory",
                      "partner_rampedup"
                    ]
                  },
                  "compiled_at": {
                    "type": "string",
                    "format": "date"
                  },
                  "last_verified_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "telephone",
                      "web",
                      "register"
                    ]
                  }
                },
                "required": [
                  "source",
                  "compiled_at",
                  "last_verified_at",
                  "method"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who compiled the contact, when, and how it was last confirmed."
          },
          "email": {
            "description": "The latest email verification: date, provider result and location.",
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "verified_at": {
                    "type": "string",
                    "format": "date"
                  },
                  "result": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "catch_all",
                      "unknown",
                      "invalid",
                      "disposable"
                    ]
                  },
                  "provider_location": {
                    "type": "string",
                    "enum": [
                      "UK",
                      "EU",
                      "US"
                    ]
                  }
                },
                "required": [
                  "verified_at",
                  "result",
                  "provider_location"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "company",
          "contact"
        ],
        "description": "Source per entity, answering the ICO questions who compiled it and where from."
      },
      "ProvenanceCard": {
        "type": "object",
        "properties": {
          "sources": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string",
              "enum": [
                "emailmovers_research",
                "companies_house",
                "onspd",
                "ukbizdirectory",
                "partner_rampedup"
              ]
            },
            "description": "The source of each field shown, such as title: emailmovers_research."
          },
          "first_seen_at": {
            "type": "string",
            "format": "date"
          },
          "last_verified_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "method": {
            "type": "string",
            "enum": [
              "telephone",
              "web",
              "register"
            ]
          },
          "companies_house_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "company_status": {
            "type": "string"
          },
          "article14_status": {
            "type": "string",
            "enum": [
              "notified",
              "publicly_notified_disproportionate_effort",
              "pending_within_window"
            ]
          },
          "tps_ctps_screened_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ]
          }
        },
        "required": [
          "sources",
          "first_seen_at",
          "last_verified_at",
          "method",
          "companies_house_number",
          "company_status",
          "article14_status",
          "tps_ctps_screened_at",
          "lawful_basis"
        ],
        "description": "The ICO due diligence answers for one record, as shown on the sample row."
      },
      "Purchase": {
        "type": "object",
        "properties": {
          "credits_to_buy": {
            "type": "integer",
            "minimum": 0,
            "description": "credits_required less the balance: all of it when signed out, 0 when the balance covers the order."
          },
          "cheapest": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
              },
              {
                "type": "null"
              }
            ],
            "description": "The id of the cheapest option; null when nothing needs buying."
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "What the cheapest option costs, excluding VAT; 0 when nothing needs buying."
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseOption"
            },
            "description": "Cheapest first: the per-contact scale, and the credit pack (with any rest at the scale) when it is on sale. At the same price, the option that buys more credits comes first."
          }
        },
        "required": [
          "credits_to_buy",
          "cheapest",
          "gbp_ex_vat",
          "options"
        ],
        "description": "How to buy the credits the order needs, worked out by one function (cheapestPurchase) everywhere a price is shown. The caller's own, like the balance: read fresh on every read of the quote."
      },
      "PurchaseAttention": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "enum": [
              "checkout_mismatch",
              "billed_outside_uk"
            ],
            "description": "checkout_mismatch: Stripe says it is paid but the checkout does not match this purchase, so no credits were added; billed_outside_uk: credited, but the billing address is not in the UK."
          },
          "detail": {
            "type": "string",
            "description": "What a person should look at, in plain English."
          },
          "since": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "reason",
          "detail",
          "since"
        ],
        "description": "A purchase a person at Emailmovers looks at. It is flagged on the purchase, and emailed to the payment alerts address when one is set."
      },
      "PurchaseLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "A credit pack id, or per_contact_scale."
          },
          "quantity": {
            "type": "integer",
            "minimum": 0,
            "description": "Credit packs bought, or credits bought at the scale."
          },
          "credits": {
            "type": "integer",
            "minimum": 0
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          }
        },
        "required": [
          "id",
          "quantity",
          "credits",
          "gbp_ex_vat"
        ],
        "description": "One thing bought: credit packs, or credits at the scale."
      },
      "PurchaseOption": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "per_contact_scale, or the id of the credit pack the option is built on (with any rest at the scale). The same between quotes, so a choice survives a fresh quote."
          },
          "label": {
            "type": "string",
            "description": "Such as 12,000 records at 22p."
          },
          "credits": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits the option buys."
          },
          "gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "credits_left_over": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits that stay in the balance after the order."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseLine"
            }
          }
        },
        "required": [
          "id",
          "label",
          "credits",
          "gbp_ex_vat",
          "credits_left_over",
          "lines"
        ],
        "description": "One way to buy the credits the order needs."
      },
      "Push": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^psh_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a CRM push id: psh_ followed by a 26 character ULID in upper case Crockford base32, such as psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5.",
            "examples": [
              "psh_01JB4NC3W2X6Y7Z8A1B2C3D4E5"
            ]
          },
          "order_id": {
            "type": "string",
            "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "examples": [
              "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
            ]
          },
          "connection_id": {
            "type": "string",
            "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
            "examples": [
              "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
            ]
          },
          "dry_run": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "completed",
              "partial",
              "failed"
            ]
          },
          "summary": {
            "type": "object",
            "properties": {
              "to_create": {
                "type": "integer",
                "minimum": 0
              },
              "to_update": {
                "type": "integer",
                "minimum": 0
              },
              "already_present": {
                "type": "integer",
                "minimum": 0
              },
              "skipped": {
                "type": "integer",
                "minimum": 0
              },
              "failed": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "to_create",
              "to_update",
              "already_present",
              "skipped",
              "failed"
            ]
          },
          "property_group": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "mydatahub_record_id",
                "licence_expires_at",
                "lawful_basis",
                "article14_status",
                "tps_ctps_screened_at",
                "subscriber_class",
                "suppression_status",
                "compliance_receipt_url"
              ]
            },
            "description": "The MyDataHub property group written on every record (CrmPropertyGroup)."
          },
          "sample": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrmPropertyGroup"
              },
              {
                "type": "null"
              }
            ],
            "description": "On a dry run: the property group the first record would carry."
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "record_id": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "record_id",
                "message"
              ]
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "order_id",
          "connection_id",
          "dry_run",
          "status",
          "summary",
          "property_group",
          "sample",
          "errors",
          "created_at",
          "completed_at"
        ],
        "description": "A CRM push or its dry run, such as 4,102 to create and 0 already in your HubSpot."
      },
      "PushCompletedEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "push.completed"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "$ref": "#/components/schemas/Push"
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A CRM push finished."
      },
      "PushFailedEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "push.failed"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "$ref": "#/components/schemas/Push"
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A CRM push failed."
      },
      "PushPartialEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "push.partial"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "$ref": "#/components/schemas/Push"
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A CRM push partly finished; retry the failed records."
      },
      "PushRequest": {
        "type": "object",
        "properties": {
          "connection_id": {
            "type": "string",
            "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a CRM connection id: conn_ followed by a 26 character ULID in upper case Crockford base32, such as conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G.",
            "examples": [
              "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
            ]
          },
          "dry_run": {
            "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.",
            "default": true,
            "type": "boolean"
          },
          "update_existing": {
            "description": "Update records already in the CRM, matched on mydatahub_record_id. Default true.",
            "default": true,
            "type": "boolean"
          },
          "confirmation_token": {
            "type": "string",
            "minLength": 16,
            "maxLength": 2000,
            "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."
          }
        },
        "required": [
          "connection_id"
        ],
        "additionalProperties": false,
        "description": "Push an order's records to a connection. Records only; nothing is ever sent to the contacts. A live push without approval returns 403 confirmation-required."
      },
      "Quality": {
        "type": "object",
        "properties": {
          "email_coverage_pct": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Records with a named email as a share of the count."
          },
          "verified_90d_pct": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "Share of emails with a provider result of ok in the last 90 days."
          },
          "verified_measured_at": {
            "type": "string",
            "format": "date"
          },
          "deliverability": {
            "description": "Score distribution: good 70 to 100, risky 40 to 69, poor under 40.",
            "type": "object",
            "properties": {
              "good": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "risky": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "poor": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              }
            },
            "required": [
              "good",
              "risky",
              "poor"
            ]
          },
          "avg_days_since_verification": {
            "type": "number",
            "minimum": 0
          },
          "phone_coverage_pct": {
            "description": "Share with a validated number, when phone is requested.",
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "tps_ctps_screened_at": {
            "description": "The version's TPS and CTPS screen date, when phone is requested and a number in it is screened; each number carries its own status and screen date.",
            "type": "string",
            "format": "date"
          }
        },
        "required": [
          "email_coverage_pct",
          "verified_90d_pct"
        ],
        "description": "Quality signals shown with every count."
      },
      "Quote": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/MachineQuote"
          },
          {
            "$ref": "#/components/schemas/SalesQuote"
          }
        ],
        "description": "A machine quote (kind machine, 24 hours) or a human sales quote (kind sales, 14 days).",
        "discriminator": {
          "propertyName": "kind",
          "mapping": {
            "machine": "#/components/schemas/MachineQuote",
            "sales": "#/components/schemas/SalesQuote"
          }
        }
      },
      "QuoteBlocker": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "insufficient_credits",
              "account_required",
              "agent_budget_exceeded",
              "dataset_unavailable",
              "count_expired"
            ]
          },
          "detail": {
            "type": "string"
          },
          "top_up_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "code",
          "detail"
        ],
        "description": "Something that stops create_order until it is fixed."
      },
      "QuoteRequest": {
        "type": "object",
        "properties": {
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Za-z2-7]{20}$",
            "description": "A count id from POST /v1/counts or count_audience. Either case is accepted; responses use upper case.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "field_set": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "description": "A field set id from GET /v1/field-sets, such as standard."
          },
          "limit": {
            "description": "Records to buy; left out, the whole count.",
            "type": "integer",
            "minimum": 1,
            "maximum": 1000000
          },
          "dedupe_against": {
            "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.",
            "default": "previous_orders",
            "type": "string",
            "enum": [
              "none",
              "previous_orders",
              "crm",
              "previous_orders_and_crm"
            ]
          },
          "connection_id": {
            "description": "The CRM connection to check, only with dedupe_against crm or previous_orders_and_crm.",
            "type": "string",
            "pattern": "^conn_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "examples": [
              "conn_01JB3Y2X6Y7Z8A1B2C3D4E5F6G"
            ]
          },
          "licence": {
            "default": "multi_use_12m",
            "type": "string",
            "enum": [
              "multi_use_12m",
              "outright"
            ],
            "description": "multi_use_12m (12 month multi-use, every plan) or outright (1.8 credits a record, proposed)."
          }
        },
        "required": [
          "count_id",
          "field_set"
        ],
        "additionalProperties": false,
        "description": "What to price: a count, a field set, how many records and the licence. Free, and needs no account.",
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "dedupe_against": {
                  "enum": [
                    "crm",
                    "previous_orders_and_crm"
                  ]
                }
              },
              "required": [
                "dedupe_against"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "connection_id": true
              },
              "required": [
                "connection_id"
              ]
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "connection_id": true
              },
              "required": [
                "connection_id"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "dedupe_against": {
                  "enum": [
                    "crm",
                    "previous_orders_and_crm"
                  ]
                }
              },
              "required": [
                "dedupe_against"
              ]
            }
          }
        ]
      },
      "QuoteSignature": {
        "type": "object",
        "properties": {
          "alg": {
            "type": "string",
            "const": "ES256"
          },
          "kid": {
            "type": "string",
            "description": "The signing key id in jwks_url."
          },
          "jwks_url": {
            "type": "string",
            "format": "uri"
          },
          "jws": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$",
            "description": "A compact JWS whose payload is the quote's id, organisation_id, count_id, dataset_version, records, credits_required, gbp_ex_vat, licence, expires_at."
          }
        },
        "required": [
          "alg",
          "kid",
          "jwks_url",
          "jws"
        ],
        "description": "The signature over the machine quote's price, so an agent can hand the quote to another agent and both can check it. Verify it with the key at jwks_url."
      },
      "RadiusCentre": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/PlaceCentre"
          },
          {
            "$ref": "#/components/schemas/PostcodeCentre"
          },
          {
            "$ref": "#/components/schemas/PointCentre"
          }
        ],
        "description": "The centre of a radius: a place, a postcode or a latitude and longitude."
      },
      "RateLimit": {
        "type": "object",
        "properties": {
          "tier": {
            "type": "string",
            "enum": [
              "anonymous",
              "free",
              "paid"
            ]
          },
          "counts_per_minute": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "counts_per_hour": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "counts_per_day": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "remaining": {
            "type": "integer",
            "minimum": 0
          },
          "resets_at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "to_confirm"
            ]
          }
        },
        "required": [
          "tier",
          "counts_per_minute",
          "counts_per_hour",
          "counts_per_day",
          "remaining",
          "resets_at",
          "status"
        ],
        "description": "The caller's count limits and what remains in the window."
      },
      "ReceiptClaims": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string",
            "pattern": "^rcpt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a compliance receipt id: rcpt_ followed by a 26 character ULID in upper case Crockford base32, such as rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R.",
            "examples": [
              "rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R"
            ]
          },
          "order_id": {
            "type": "string",
            "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "examples": [
              "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
            ]
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "records_delivered": {
            "type": "integer",
            "minimum": 0
          },
          "removed_by_suppression": {
            "type": "integer",
            "minimum": 0
          },
          "counts": {
            "type": "object",
            "properties": {
              "subscriber_class": {
                "type": "object",
                "properties": {
                  "ltd": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "plc": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "llp": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "scottish_partnership": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "public_body": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "charity_incorporated": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "sole_trader": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "ordinary_partnership": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "unknown": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "ltd",
                  "plc",
                  "llp",
                  "scottish_partnership",
                  "public_body",
                  "charity_incorporated",
                  "sole_trader",
                  "ordinary_partnership",
                  "unknown"
                ]
              },
              "tps_ctps_status": {
                "type": "object",
                "properties": {
                  "clear": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "tps_registered": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "ctps_registered": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "tps_or_ctps_registered": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "not_screened": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "clear",
                  "tps_registered",
                  "ctps_registered",
                  "tps_or_ctps_registered",
                  "not_screened"
                ]
              },
              "article14_status": {
                "type": "object",
                "properties": {
                  "notified": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "publicly_notified_disproportionate_effort": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "pending_within_window": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "notified",
                  "publicly_notified_disproportionate_effort",
                  "pending_within_window"
                ]
              }
            },
            "required": [
              "subscriber_class",
              "tps_ctps_status",
              "article14_status"
            ]
          },
          "lawful_basis": {
            "type": "string",
            "enum": [
              "legitimate_interests_art6_1_f"
            ]
          },
          "lia_ref": {
            "type": "string"
          },
          "licence": {
            "$ref": "#/components/schemas/Licence"
          },
          "residency_statement_version": {
            "type": "string"
          },
          "sub_processor_list_version": {
            "type": "string"
          },
          "verified_within_days": {
            "type": "object",
            "properties": {
              "within_30_days": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "within_60_days": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "within_90_days": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              }
            },
            "required": [
              "within_30_days",
              "within_60_days",
              "within_90_days"
            ],
            "description": "Share of delivered emails verified within 30, 60 and 90 days."
          },
          "content_sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "SHA-256 of the delivered file, lower case hex."
          }
        },
        "required": [
          "receipt_id",
          "order_id",
          "issued_at",
          "dataset_version",
          "records_delivered",
          "removed_by_suppression",
          "counts",
          "lawful_basis",
          "lia_ref",
          "licence",
          "residency_statement_version",
          "sub_processor_list_version",
          "verified_within_days",
          "content_sha256"
        ],
        "description": "The decoded payload of a compliance receipt."
      },
      "ReceiptVerification": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean",
            "description": "The signature checks out against the published key."
          },
          "order_exists": {
            "type": "boolean"
          },
          "licence_in_force_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ]
          },
          "revoked": {
            "type": "boolean"
          },
          "receipt_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^rcpt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: a compliance receipt id: rcpt_ followed by a 26 character ULID in upper case Crockford base32, such as rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R.",
                "examples": [
                  "rcpt_01JB4NA2Q5W8ZAK8Q2V7XN3M9R"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "checked_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "valid",
          "order_exists",
          "licence_in_force_until",
          "revoked",
          "receipt_id",
          "checked_at"
        ],
        "description": "The verdict on a receipt, so one agent can prove to another a list is licensed."
      },
      "ReceiptVerifyRequest": {
        "type": "object",
        "properties": {
          "jws": {
            "type": "string",
            "minLength": 10,
            "maxLength": 20000,
            "description": "The compact JWS to check."
          }
        },
        "required": [
          "jws"
        ],
        "additionalProperties": false,
        "description": "A compliance receipt to verify."
      },
      "RecordsPage": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string",
            "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
            "examples": [
              "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
            ]
          },
          "format": {
            "type": "string",
            "const": "json"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
            },
            "description": "The field set's columns in this page."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactRecord"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ]
          },
          "remaining": {
            "type": "integer",
            "minimum": 0,
            "description": "Records after this page."
          },
          "approx_tokens": {
            "description": "A rough token size of this page; pages stay under about 8,000 tokens.",
            "type": "integer",
            "minimum": 0
          },
          "licence": {
            "$ref": "#/components/schemas/Licence"
          }
        },
        "required": [
          "order_id",
          "format",
          "fields",
          "data",
          "has_more",
          "next_cursor",
          "remaining",
          "licence"
        ],
        "description": "A page of delivered records with the licence block. Re-fetching records under licence costs 0 credits."
      },
      "ResolvedCentre": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string"
          },
          "code": {
            "type": [
              "string",
              "null"
            ]
          },
          "lat": {
            "type": "number"
          },
          "lon": {
            "type": "number"
          },
          "radius_miles": {
            "type": "number"
          },
          "postcode_districts_matched": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "label",
          "code",
          "lat",
          "lon",
          "radius_miles",
          "postcode_districts_matched"
        ],
        "description": "A radius centre as the engine resolved it."
      },
      "SalesQuote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^qte_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a quote id: qte_ followed by a 26 character ULID in upper case Crockford base32, such as qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3.",
            "examples": [
              "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
            ]
          },
          "kind": {
            "type": "string",
            "const": "sales"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "accepted",
              "paid",
              "expired",
              "withdrawn"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "valid_until": {
            "type": "string",
            "format": "date",
            "description": "14 days after creation."
          },
          "created_by": {
            "type": "object",
            "properties": {
              "role": {
                "type": "string",
                "enum": [
                  "user",
                  "account_manager"
                ]
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "role",
              "name"
            ]
          },
          "customer": {
            "type": "string",
            "description": "The organisation the quote is for."
          },
          "count_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^cnt_[A-Z2-7]{20}$",
                "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
                "examples": [
                  "cnt_7K2PQ4MAXN3R6TBY5WDZ"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "field_set": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$"
          },
          "records": {
            "type": "integer",
            "minimum": 0,
            "description": "Records the quote covers."
          },
          "credits_per_record": {
            "type": "number",
            "minimum": 0,
            "description": "Credits a record under the licence: 1, or 1.8 outright (proposed)."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SalesQuoteLine"
            }
          },
          "subtotal_gbp_ex_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "vat_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "total_gbp_inc_vat": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "balance_after": {
            "description": "The customer's credits after the order. Paying by card or invoice leaves the balance as it is; null when the customer has no account yet.",
            "type": [
              "number",
              "null"
            ]
          },
          "licence": {
            "$ref": "#/components/schemas/Licence"
          },
          "warranty": {
            "$ref": "#/components/schemas/Warranty"
          },
          "payment_methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "card",
                "invoice"
              ]
            }
          },
          "pay_url": {
            "type": "string",
            "format": "uri",
            "description": "Pay by card or request an invoice link, no account needed."
          },
          "pdf_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "id",
          "kind",
          "status",
          "created_at",
          "valid_until",
          "created_by",
          "customer",
          "count_id",
          "field_set",
          "records",
          "credits_per_record",
          "lines",
          "subtotal_gbp_ex_vat",
          "vat_gbp",
          "total_gbp_inc_vat",
          "balance_after",
          "licence",
          "warranty",
          "payment_methods",
          "pay_url",
          "pdf_url"
        ],
        "description": "A human sales quote: 14 days, a PDF, payable by card or invoice link, created in the app or by an account manager. Not a machine quote; create_order does not take it."
      },
      "SalesQuoteLine": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "minimum": 0
          },
          "unit_price_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          },
          "amount_gbp": {
            "type": "number",
            "minimum": 0,
            "description": "Pounds sterling excluding VAT, to two decimal places."
          }
        },
        "required": [
          "description",
          "quantity",
          "unit_price_gbp",
          "amount_gbp"
        ],
        "description": "One line of a sales quote, excluding VAT."
      },
      "SampleDownload": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "empty",
              "downloaded"
            ],
            "description": "ready: download_url serves the sample once; empty: no record of the audience can be sent as a sample now, and nothing is supplied; downloaded: the sample was already served, and is never served twice."
          },
          "records": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "description": "Records in the sample: up to 10, fewer when fewer are left."
          },
          "download_url": {
            "description": "A relative link on this host to the CSV, whose first lines are the licence. It works once, for 5 minutes, from the address that asked for it. Null unless ready.",
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When download_url stops working. Null unless ready."
          }
        },
        "required": [
          "status",
          "records",
          "download_url",
          "expires_at"
        ],
        "description": "The confirmed sample: a single-use link to it, or why there is none. Confirming chooses the records, read afresh against every suppression."
      },
      "SampleDownloadCreate": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{40,64}$",
            "description": "The token from the emailed link (the last part of /samples/confirm/{token}). Only a press of the confirmation page's button sends it, so a link scanner that opens the page uses nothing up."
          }
        },
        "required": [
          "token"
        ],
        "additionalProperties": false,
        "description": "The emailed token."
      },
      "SampleRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^smr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a sample request id: smr_ followed by a 26 character ULID in upper case Crockford base32, such as smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6.",
            "examples": [
              "smr_01JB4P2Q5W8ZAK8Q2V7XN3M9R6"
            ]
          },
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting_email",
              "email_sent",
              "confirmed",
              "downloaded",
              "expired"
            ],
            "description": "awaiting_email until the address is sent; email_sent once it was checked (a refused address reads the same); confirmed once the link is opened; downloaded once the sample is served; expired after its time."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the request, or the link emailed for it, stops working: 24 hours."
          }
        },
        "required": [
          "id",
          "count_id",
          "status",
          "created_at",
          "expires_at"
        ],
        "description": "A request for a sample of a counted audience. It never shows the address or the records."
      },
      "SampleRequestCreate": {
        "type": "object",
        "properties": {
          "count_id": {
            "type": "string",
            "pattern": "^cnt_[A-Z2-7]{20}$",
            "description": "Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ.",
            "examples": [
              "cnt_7K2PQ4MAXN3R6TBY5WDZ"
            ]
          }
        },
        "required": [
          "count_id"
        ],
        "additionalProperties": false,
        "description": "The count to sample."
      },
      "SampleRequestEmail": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "The person's work email address, sent by the calling server from its own form, never through a model. Free webmail addresses are refused."
          },
          "follow_up": {
            "type": "boolean",
            "description": "Whether the person ticked the box allowing Emailmovers to email them about the sample."
          },
          "wording": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40,
            "description": "The version of the wording the person saw beside the field and the box."
          }
        },
        "required": [
          "email",
          "follow_up",
          "wording"
        ],
        "additionalProperties": false,
        "description": "The address to confirm, and the person's choice on follow-up."
      },
      "SampleRequestEmailAccepted": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "const": "check_your_inbox",
            "description": "The same answer whether the address was accepted or refused (a suppressed address, an objection, a limit), so the call cannot be used to test addresses."
          }
        },
        "required": [
          "status"
        ],
        "description": "The request was taken."
      },
      "SavedAudience": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^aud_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA.",
            "examples": [
              "aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA"
            ]
          },
          "name": {
            "type": "string"
          },
          "audience": {
            "$ref": "#/components/schemas/Audience"
          },
          "brief": {
            "description": "The brief it was compiled from, if any.",
            "type": [
              "string",
              "null"
            ]
          },
          "current_count": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AudienceCountSummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_refreshed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string",
            "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8.",
            "examples": [
              "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The audience in the app, mydatahub.emailmovers.com/audiences/{id}."
          }
        },
        "required": [
          "id",
          "name",
          "audience",
          "brief",
          "current_count",
          "last_refreshed_at",
          "created_at",
          "updated_at",
          "created_by",
          "url"
        ],
        "description": "A named audience shared across the organisation, with its current count."
      },
      "SavedAudienceList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SavedAudience"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of saved audiences, newest first."
      },
      "SavedAudienceRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "audience": {
            "$ref": "#/components/schemas/Audience"
          },
          "brief": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "name",
          "audience"
        ],
        "additionalProperties": false,
        "description": "A named audience to save."
      },
      "SavedAudienceUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "audience": {
            "$ref": "#/components/schemas/Audience"
          },
          "brief": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false,
        "description": "Members to change on a saved audience, at least one.",
        "minProperties": 1
      },
      "SicCode": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "label": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "label"
        ],
        "description": "A SIC 2007 code and its label, such as 25620 Machining."
      },
      "SinceFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "contact.last_validated_at",
              "email.last_verified_at",
              "signal.type",
              "signal.observed_at"
            ]
          },
          "op": {
            "type": "string",
            "const": "since"
          },
          "days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3650
          },
          "values": {
            "description": "For signal.type only: the signal types to look for, such as company.incorporated.",
            "minItems": 1,
            "maxItems": 10000,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        },
        "required": [
          "field",
          "op",
          "days"
        ],
        "additionalProperties": false,
        "description": "Within the last N days: a date field, or a Companies House signal of the listed types on signal.type.",
        "examples": [
          {
            "field": "signal.type",
            "op": "since",
            "values": [
              "company.incorporated"
            ],
            "days": 90
          }
        ],
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "contact.last_validated_at"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": false
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "email.last_verified_at"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": false
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "signal.type"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "required": [
                "values"
              ],
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "company.incorporated",
                      "company.name_changed",
                      "company.registered_office_moved",
                      "company.sic_changed",
                      "company.charge_created",
                      "company.accounts_overdue",
                      "company.confirmation_statement_overdue"
                    ]
                  }
                }
              }
            }
          },
          {
            "if": {
              "type": "object",
              "properties": {
                "field": {
                  "const": "signal.observed_at"
                }
              },
              "required": [
                "field"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": false
              }
            }
          }
        ]
      },
      "StandardApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^key_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an API key id: key_ followed by a 26 character ULID in upper case Crockford base32, such as key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "key_01JB3Z4Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "label": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "live keys (mdh_live_) spend real credits; test keys (mdh_test_) return synthetic data and never charge."
          },
          "prefix": {
            "type": "string",
            "description": "The first characters of the secret, such as mdh_live_7Kq2."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "account:read",
                "counts:read",
                "previews:read",
                "audiences:read",
                "audiences:write",
                "quotes:read",
                "orders:read",
                "orders:write",
                "records:read",
                "enrich:write",
                "suppressions:read",
                "suppressions:write",
                "pushes:write",
                "webhooks:write",
                "samples:request",
                "admin"
              ]
            }
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$"
                },
                {
                  "type": "string",
                  "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$"
                }
              ],
              "description": "An IPv4 or IPv6 range in CIDR notation, such as 203.0.113.0/24."
            },
            "description": "CIDR ranges the key may be used from; empty allows any address."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string",
            "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8.",
            "examples": [
              "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "revoked_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "type": "string",
            "const": "standard"
          }
        },
        "required": [
          "id",
          "label",
          "mode",
          "prefix",
          "scopes",
          "ip_allowlist",
          "created_at",
          "created_by",
          "last_used_at",
          "expires_at",
          "revoked_at",
          "kind"
        ],
        "description": "An API key for your own code."
      },
      "SubProcessor": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "transfer_mechanism": {
            "type": "string"
          },
          "added_at": {
            "type": "string",
            "format": "date"
          }
        },
        "required": [
          "name",
          "purpose",
          "location",
          "transfer_mechanism",
          "added_at"
        ],
        "description": "One sub-processor on the trust page."
      },
      "SubProcessorChange": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "name": {
            "type": "string"
          },
          "change": {
            "type": "string",
            "enum": [
              "added",
              "removed",
              "changed"
            ]
          },
          "summary": {
            "type": "string"
          }
        },
        "required": [
          "date",
          "name",
          "change",
          "summary"
        ],
        "description": "One entry in the change log."
      },
      "SuppressionCheck": {
        "type": "object",
        "properties": {
          "checked_at": {
            "type": "string",
            "format": "date-time"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "record_id": {
                  "type": "string",
                  "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                  "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
                  "examples": [
                    "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
                  ]
                },
                "suppressed": {
                  "type": "boolean"
                },
                "suppression_status": {
                  "type": "string",
                  "enum": [
                    "none",
                    "objected_to_emailmovers",
                    "objected_to_licensee",
                    "deceased",
                    "left_company"
                  ]
                },
                "list_ids": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                    "description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA.",
                    "examples": [
                      "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
                    ]
                  }
                }
              },
              "required": [
                "record_id",
                "suppressed",
                "suppression_status",
                "list_ids"
              ]
            }
          }
        },
        "required": [
          "checked_at",
          "results"
        ],
        "description": "Suppression status per record, as of now."
      },
      "SuppressionCheckRequest": {
        "type": "object",
        "properties": {
          "record_ids": {
            "minItems": 1,
            "maxItems": 1000,
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
              "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
              "examples": [
                "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
              ]
            }
          }
        },
        "required": [
          "record_ids"
        ],
        "additionalProperties": false,
        "description": "Records to check before a send."
      },
      "SuppressionChecksum": {
        "type": "object",
        "properties": {
          "list_id": {
            "type": "string",
            "pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "checksum": {
            "type": "string"
          },
          "row_count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "list_id",
          "checksum",
          "row_count"
        ],
        "description": "A suppression list as the count read it."
      },
      "SuppressionCreatedEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "suppression.created"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "$ref": "#/components/schemas/SuppressionNotice"
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "An objection reached a record your organisation holds. Suppress it before any send."
      },
      "SuppressionList": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "email",
              "domain",
              "phone",
              "company_number",
              "title_term"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "upload",
              "objections"
            ],
            "description": "upload for a list you sent; objections for the organisation's own list, which gathers objections you report and database-wide objections on records you hold."
          },
          "row_count": {
            "type": "integer",
            "minimum": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^usr_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8.",
                "examples": [
                  "usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "added_since": {
            "description": "With since: the records added to this list after that time, for pull.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuppressionNotice"
            }
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "source",
          "row_count",
          "created_at",
          "updated_at",
          "created_by"
        ],
        "description": "A named list of hashed emails, domains, phones, company numbers or title terms, applied to every count and order at no charge."
      },
      "SuppressionListPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuppressionList"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of suppression lists."
      },
      "SuppressionListRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "kind": {
            "type": "string",
            "enum": [
              "email",
              "domain",
              "phone",
              "company_number",
              "title_term"
            ]
          },
          "values": {
            "minItems": 1,
            "maxItems": 100000,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 320
            },
            "description": "Raw values (trimmed, lower cased and hashed on arrival) or SHA-256 hex hashes. Domains may use a wildcard such as *.gmail.com; phones are E.164; company numbers are eight characters."
          },
          "hashed": {
            "description": "True when values are already SHA-256 hashes, each 64 lower case hex characters. Default false.",
            "default": false,
            "type": "boolean"
          },
          "dpa_accepted_version": {
            "description": "The version of the Article 28 data processing agreement the person uploading accepts: the account's agreements.dpa.version. The app sends it with the first upload, and again when a new version is in force. Only a signed-in person accepts it.",
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "name",
          "kind",
          "values"
        ],
        "additionalProperties": false,
        "description": "A list to upload. Values are stored as SHA-256 hashes only. The first upload asks you to accept the Article 28 DPA in the app, and the account's agreements.dpa keeps who accepted which version and when.",
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "hashed": {
                  "const": true
                }
              },
              "required": [
                "hashed"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "values": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  }
                }
              }
            }
          }
        ]
      },
      "SuppressionNotice": {
        "type": "object",
        "properties": {
          "record_id": {
            "type": "string",
            "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
            "examples": [
              "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "none",
              "objected_to_emailmovers",
              "objected_to_licensee",
              "deceased",
              "left_company"
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "licensee",
              "emailmovers"
            ]
          },
          "suppressed_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "record_id",
          "reason",
          "scope",
          "suppressed_at"
        ],
        "description": "A record you hold that is now suppressed, as the suppression.created webhook carries it."
      },
      "SuppressionRemoval": {
        "type": "object",
        "properties": {
          "list_id": {
            "type": "string",
            "pattern": "^sup_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a suppression list id: sup_ followed by a 26 character ULID in upper case Crockford base32, such as sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "removed": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "list_id",
          "removed"
        ],
        "description": "Records one suppression list removed."
      },
      "SuppressionUpload": {
        "type": "object",
        "properties": {
          "list": {
            "$ref": "#/components/schemas/SuppressionList"
          },
          "rows_read": {
            "type": "integer",
            "minimum": 0
          },
          "rows_valid": {
            "type": "integer",
            "minimum": 0
          },
          "rows_skipped": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "row": {
                  "type": "integer",
                  "minimum": 1
                },
                "reason": {
                  "type": "string"
                }
              },
              "required": [
                "row",
                "reason"
              ]
            }
          }
        },
        "required": [
          "list",
          "rows_read",
          "rows_valid",
          "rows_skipped"
        ],
        "description": "A saved list and what the upload read: rows read, valid and skipped with reasons."
      },
      "TitleExpansion": {
        "type": "object",
        "properties": {
          "dataset_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$",
            "description": "The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable.",
            "examples": [
              "2026-W39"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "contains",
              "starts_with",
              "exact"
            ],
            "description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
          },
          "expand": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "plural_singular",
                "department_synonyms",
                "ampersand_and",
                "abbreviations",
                "permutations"
              ]
            }
          },
          "terms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExpandedTerm"
            }
          },
          "total_contacts": {
            "$ref": "#/components/schemas/CellCount"
          },
          "bundle": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "enum": [
                      "sdm",
                      "manager_and_above",
                      "owner_managed"
                    ]
                  },
                  "label": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "confirmed",
                      "proposed",
                      "to_confirm"
                    ]
                  },
                  "resolves_to": {
                    "$ref": "#/components/schemas/WhereNode"
                  }
                },
                "required": [
                  "id",
                  "label",
                  "status",
                  "resolves_to"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "filter": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Filter"
              },
              {
                "type": "null"
              }
            ],
            "description": "A ready matches filter for the terms, or null for a bundle."
          },
          "disclosure": {
            "$ref": "#/components/schemas/Disclosure"
          }
        },
        "required": [
          "dataset_version",
          "mode",
          "expand",
          "terms",
          "total_contacts",
          "bundle",
          "filter",
          "disclosure"
        ],
        "description": "Every expanded title with a count, or what a bundle resolves to. Nothing is resolved silently."
      },
      "TitleExpansionRequest": {
        "type": "object",
        "properties": {
          "terms": {
            "description": "Title keywords to expand, such as marketing manager.",
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "bundle": {
            "description": "A title bundle to show: sdm, manager_and_above or owner_managed.",
            "type": "string",
            "enum": [
              "sdm",
              "manager_and_above",
              "owner_managed"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "contains",
              "starts_with",
              "exact"
            ],
            "description": "contains (the default) matches titles containing a term, starts_with matches titles beginning with it, exact takes verbatim titles with no expansion."
          },
          "expand": {
            "description": "Expansion sets to apply, each once. Left out, the four default sets apply.",
            "uniqueItems": true,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "plural_singular",
                "department_synonyms",
                "ampersand_and",
                "abbreviations",
                "permutations"
              ]
            }
          },
          "dataset": {
            "type": "string",
            "enum": [
              "uk_contacts",
              "ie_contacts",
              "global_contacts"
            ],
            "description": "The dataset an audience draws from. uk_contacts is live; ie_contacts and global_contacts are listed but not yet served."
          }
        },
        "additionalProperties": false,
        "description": "Keywords or a bundle to expand into an editable title list: exactly one of terms or bundle.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "terms": true
            },
            "required": [
              "terms"
            ]
          },
          {
            "type": "object",
            "properties": {
              "bundle": true
            },
            "required": [
              "bundle"
            ]
          }
        ]
      },
      "TpsScreen": {
        "type": "object",
        "properties": {
          "screened_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date"
              },
              {
                "type": "null"
              }
            ],
            "description": "The version's TPS and CTPS screen date (quality.tps_ctps_screened_at); null when no number in it is screened."
          },
          "age_days": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ],
            "description": "Days from the screen date to today; null when no number is screened."
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "warning",
              "expired"
            ],
            "description": "ok up to 21 days, warning from 22 to 28 days, and expired after 28 days, when counts, samples, quotes and orders with telephone in play are refused with tps-screen-expired. ok when no number is screened."
          }
        },
        "required": [
          "screened_at",
          "age_days",
          "status"
        ],
        "description": "The TPS and CTPS screen of the current dataset version, on today's date."
      },
      "TrustDocument": {
        "type": "object",
        "properties": {
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "company": {
            "type": "object",
            "properties": {
              "legal_name": {
                "type": "string"
              },
              "company_number": {
                "type": "string"
              },
              "trading_as": {
                "type": "string"
              }
            },
            "required": [
              "legal_name",
              "company_number",
              "trading_as"
            ]
          },
          "ico_registration": {
            "type": "object",
            "properties": {
              "number": {
                "type": "string"
              },
              "expires_on": {
                "type": "string",
                "format": "date"
              },
              "register_url": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "number",
              "expires_on",
              "register_url"
            ]
          },
          "lawful_basis": {
            "type": "object",
            "properties": {
              "basis": {
                "type": "string",
                "enum": [
                  "legitimate_interests_art6_1_f"
                ]
              },
              "lia_ref": {
                "type": "string"
              },
              "lia_url": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "basis",
              "lia_ref",
              "lia_url"
            ]
          },
          "privacy_notice": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "versions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/NoticeVersion"
                },
                "description": "Every version of the Article 14 notice, newest first."
              }
            },
            "required": [
              "version",
              "url",
              "versions"
            ],
            "description": "The Article 14 privacy notice for contacts, with its history."
          },
          "residency": {
            "type": "object",
            "properties": {
              "statement": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            },
            "required": [
              "statement",
              "version"
            ]
          },
          "sub_processors": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string"
              },
              "notice_days": {
                "type": "integer",
                "exclusiveMinimum": 0
              },
              "notice_channels": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "email",
                    "webhook"
                  ]
                },
                "description": "How customers hear of a change 30 days ahead: by email and by webhook."
              },
              "list": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SubProcessor"
                }
              },
              "changes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SubProcessorChange"
                },
                "description": "The change log, newest first."
              }
            },
            "required": [
              "version",
              "notice_days",
              "notice_channels",
              "list",
              "changes"
            ]
          },
          "retention": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "category": {
                  "type": "string"
                },
                "period": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "confirmed",
                    "to_confirm"
                  ]
                }
              },
              "required": [
                "category",
                "period",
                "status"
              ]
            }
          },
          "complaints": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "format": "uri",
                "description": "The complaints form."
              },
              "email": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "email"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The complaints address; null until published."
              },
              "acknowledgement_days": {
                "type": "integer",
                "exclusiveMinimum": 0
              }
            },
            "required": [
              "url",
              "email",
              "acknowledgement_days"
            ]
          },
          "data_protection_lead": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                },
                "required": [
                  "name",
                  "email"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Named person and email; null until confirmed."
          },
          "datasets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Dataset"
            },
            "description": "Every dataset with owner, source, licence, refresh, residency, regulator, warranty and credits per record."
          },
          "security": {
            "type": "object",
            "properties": {
              "certifications": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "held",
                        "target"
                      ]
                    },
                    "date": {
                      "type": "string",
                      "description": "Year and month, such as 2026-10."
                    }
                  },
                  "required": [
                    "name",
                    "status",
                    "date"
                  ]
                }
              },
              "encryption": {
                "type": "object",
                "properties": {
                  "at_rest": {
                    "type": "string",
                    "description": "Such as AES-256."
                  },
                  "in_transit_minimum": {
                    "type": "string",
                    "description": "Such as TLS 1.2."
                  },
                  "key_rotation": {
                    "type": "string",
                    "description": "Such as KMS managed key rotation."
                  }
                },
                "required": [
                  "at_rest",
                  "in_transit_minimum",
                  "key_rotation"
                ],
                "description": "How data is encrypted, as the trust centre publishes it."
              },
              "data_flow_diagram_url": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "uri"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The UK data flow diagram; null until published."
              },
              "pen_test_summary_url": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "uri"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The latest penetration test summary; null until one is published."
              },
              "caiq_url": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "uri"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "CAIQ v4 answers; null until published."
              },
              "status_page": {
                "type": "string",
                "format": "uri"
              },
              "security_txt": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "certifications",
              "encryption",
              "data_flow_diagram_url",
              "pen_test_summary_url",
              "caiq_url",
              "status_page",
              "security_txt"
            ]
          }
        },
        "required": [
          "updated_at",
          "company",
          "ico_registration",
          "lawful_basis",
          "privacy_notice",
          "residency",
          "sub_processors",
          "retention",
          "complaints",
          "data_protection_lead",
          "datasets",
          "security"
        ],
        "description": "The trust page as data, mirrored at https://mydatahub.emailmovers.com/trust.json and the mydatahub://compliance resource."
      },
      "ValidationReportLinks": {
        "type": "object",
        "properties": {
          "pdf_url": {
            "type": "string",
            "format": "uri"
          },
          "json_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "pdf_url",
          "json_url"
        ],
        "description": "The per-order validation report: dataset version, status distribution, verification age, expected bounce band, TPS screen date, provider locations and the guarantee window."
      },
      "VerificationBadge": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/VerifiedBadge"
          },
          {
            "$ref": "#/components/schemas/OtherBadge"
          }
        ],
        "description": "A badge on a sample row. Every verified has a date.",
        "discriminator": {
          "propertyName": "badge",
          "mapping": {
            "verified": "#/components/schemas/VerifiedBadge",
            "re_checking": "#/components/schemas/OtherBadge",
            "unverified": "#/components/schemas/OtherBadge",
            "suppressed": "#/components/schemas/OtherBadge"
          }
        }
      },
      "VerifiedBadge": {
        "type": "object",
        "properties": {
          "badge": {
            "type": "string",
            "const": "verified"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "The verification date. Every verified has one."
          },
          "label": {
            "type": "string",
            "description": "Such as Verified 12 September 2026."
          }
        },
        "required": [
          "badge",
          "date",
          "label"
        ],
        "description": "Verified, with the date it was verified."
      },
      "Warranty": {
        "type": "object",
        "properties": {
          "policy": {
            "type": "string",
            "enum": [
              "replace_over_threshold_hard_bounce",
              "replace_any_hard_bounce_30d"
            ],
            "description": "replace_over_threshold_hard_bounce is the current policy: records are replaced when hard bounces exceed threshold_percent of an order. replace_any_hard_bounce_30d is proposed and not yet in force. The current policy's id replaced one that named the threshold, a change to this public enum made before v2 went live."
          },
          "threshold_percent": {
            "description": "replace_over_threshold_hard_bounce only, and required there: the share of an order, in percent, that hard bounces must exceed before records are replaced. It is the threshold the document was issued under.",
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "policy",
          "url"
        ],
        "description": "The bounce warranty that covers delivered records, with the threshold it was issued under.",
        "allOf": [
          {
            "if": {
              "type": "object",
              "properties": {
                "policy": {
                  "const": "replace_over_threshold_hard_bounce"
                }
              },
              "required": [
                "policy"
              ]
            },
            "then": {
              "type": "object",
              "properties": {
                "threshold_percent": true
              },
              "required": [
                "threshold_percent"
              ]
            },
            "else": {
              "type": "object",
              "not": {
                "type": "object",
                "properties": {
                  "threshold_percent": true
                },
                "required": [
                  "threshold_percent"
                ]
              }
            }
          }
        ]
      },
      "WarrantyReplacementEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Also sent as the webhook-id header; your idempotency key.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "type": {
            "type": "string",
            "const": "warranty.replacement_issued"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "A dated MyDataHub-Version, such as 2027-01-15."
          },
          "data": {
            "type": "object",
            "properties": {
              "order_id": {
                "type": "string",
                "pattern": "^ord_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: an order id: ord_ followed by a 26 character ULID in upper case Crockford base32, such as ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E.",
                "examples": [
                  "ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
                ]
              },
              "retired_record_id": {
                "type": "string",
                "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
                "examples": [
                  "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
                ]
              },
              "replacement_record_id": {
                "anyOf": [
                  {
                    "type": "string",
                    "pattern": "^contact_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                    "description": "Format: a contact id: contact_ followed by a 26 character ULID in upper case Crockford base32, such as contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8.",
                    "examples": [
                      "contact_01JA9X2V7XN3M9R6T1Y5W8ZAK8"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "reason": {
                "type": "string",
                "enum": [
                  "hard_bounce",
                  "job_change"
                ]
              },
              "credits_refunded": {
                "type": "number",
                "minimum": 0,
                "description": "Credits, to one decimal place: whole at 1 credit a record, fractional only where a rule is (0.1 company-only, 1.8 outright, both proposed)."
              }
            },
            "required": [
              "order_id",
              "retired_record_id",
              "replacement_record_id",
              "reason",
              "credits_refunded"
            ]
          }
        },
        "required": [
          "id",
          "type",
          "timestamp",
          "api_version",
          "data"
        ],
        "description": "A bounced or job-changed record was replaced, or re-credited."
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^whk_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: a webhook endpoint id: whk_ followed by a 26 character ULID in upper case Crockford base32, such as whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA.",
            "examples": [
              "whk_01JB3Y8Q2V7XN3M9R6T1Y5W8ZA"
            ]
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order.ready",
                "order.failed",
                "audience.refreshed",
                "credits.low",
                "credits.topped_up",
                "warranty.replacement_issued",
                "suppression.created",
                "push.completed",
                "push.partial",
                "push.failed",
                "connection.expired"
              ]
            }
          },
          "api_version": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$",
            "description": "Pinned when the endpoint is created."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "api_version",
          "status",
          "description",
          "created_at"
        ],
        "description": "Where to deliver events, and which ones."
      },
      "WebhookEndpointCreated": {
        "type": "object",
        "properties": {
          "endpoint": {
            "$ref": "#/components/schemas/WebhookEndpoint"
          },
          "secret": {
            "type": "string",
            "pattern": "^whsec_[A-Za-z0-9+/]{32,86}={0,2}$",
            "description": "The signing secret (whsec_), shown once. Rotate it from the app."
          }
        },
        "required": [
          "endpoint",
          "secret"
        ],
        "description": "A new endpoint and its signing secret, shown once."
      },
      "WebhookEndpointList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "description": "An opaque cursor from next_cursor. Pass it back unchanged."
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as cursor to fetch the next page; null on the last page."
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "description": "A page of webhook endpoints, newest first."
      },
      "WebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://"
          },
          "events": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order.ready",
                "order.failed",
                "audience.refreshed",
                "credits.low",
                "credits.topped_up",
                "warranty.replacement_issued",
                "suppression.created",
                "push.completed",
                "push.partial",
                "push.failed",
                "connection.expired"
              ]
            }
          },
          "description": {
            "type": "string",
            "maxLength": 200
          }
        },
        "required": [
          "url",
          "events"
        ],
        "additionalProperties": false,
        "description": "A new endpoint, pinned to the MyDataHub-Version of the request."
      },
      "WebhookEvent": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/OrderReadyEvent"
          },
          {
            "$ref": "#/components/schemas/OrderFailedEvent"
          },
          {
            "$ref": "#/components/schemas/AudienceRefreshedEvent"
          },
          {
            "$ref": "#/components/schemas/CreditsLowEvent"
          },
          {
            "$ref": "#/components/schemas/CreditsToppedUpEvent"
          },
          {
            "$ref": "#/components/schemas/WarrantyReplacementEvent"
          },
          {
            "$ref": "#/components/schemas/SuppressionCreatedEvent"
          },
          {
            "$ref": "#/components/schemas/PushCompletedEvent"
          },
          {
            "$ref": "#/components/schemas/PushPartialEvent"
          },
          {
            "$ref": "#/components/schemas/PushFailedEvent"
          },
          {
            "$ref": "#/components/schemas/ConnectionExpiredEvent"
          }
        ],
        "description": "A Standard Webhooks payload: {type, timestamp, data} plus the event id and the pinned api_version.",
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "order.ready": "#/components/schemas/OrderReadyEvent",
            "order.failed": "#/components/schemas/OrderFailedEvent",
            "audience.refreshed": "#/components/schemas/AudienceRefreshedEvent",
            "credits.low": "#/components/schemas/CreditsLowEvent",
            "credits.topped_up": "#/components/schemas/CreditsToppedUpEvent",
            "warranty.replacement_issued": "#/components/schemas/WarrantyReplacementEvent",
            "suppression.created": "#/components/schemas/SuppressionCreatedEvent",
            "push.completed": "#/components/schemas/PushCompletedEvent",
            "push.partial": "#/components/schemas/PushPartialEvent",
            "push.failed": "#/components/schemas/PushFailedEvent",
            "connection.expired": "#/components/schemas/ConnectionExpiredEvent"
          }
        }
      },
      "WebhookTest": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
            "description": "Format: an event id: evt_ followed by a 26 character ULID in upper case Crockford base32, such as evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M.",
            "examples": [
              "evt_01JB4NB7T1Y5W8ZAK8Q2V7XN3M"
            ]
          },
          "delivered": {
            "type": "boolean"
          },
          "status_code": {
            "type": [
              "integer",
              "null"
            ]
          },
          "duration_ms": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "event_id",
          "delivered",
          "status_code",
          "duration_ms"
        ],
        "description": "The result of sending a test event to an endpoint."
      },
      "WhereNode": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/AllGroup"
          },
          {
            "$ref": "#/components/schemas/AnyGroup"
          },
          {
            "$ref": "#/components/schemas/NotGroup"
          },
          {
            "$ref": "#/components/schemas/BundleNode"
          },
          {
            "$ref": "#/components/schemas/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."
      },
      "WhyItMatches": {
        "type": "object",
        "properties": {
          "pointer": {
            "type": "string",
            "description": "JSON pointer to the filter in the audience."
          },
          "field": {
            "type": "string"
          },
          "value": {
            "description": "The record's actual value.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "explanation": {
            "type": "string",
            "description": "Such as Marketing Director matched marketing manager through expansion."
          }
        },
        "required": [
          "pointer",
          "field",
          "value",
          "explanation"
        ],
        "description": "One predicate the record satisfies, with its value."
      },
      "WithinRadiusFilter": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "site.location"
            ]
          },
          "op": {
            "type": "string",
            "const": "within_radius"
          },
          "centre": {
            "$ref": "#/components/schemas/RadiusCentre"
          },
          "radius_miles": {
            "type": "number",
            "minimum": 1,
            "maximum": 100,
            "description": "Radius in miles, 1 to 100. Under 5 miles needs an account."
          }
        },
        "required": [
          "field",
          "op",
          "centre",
          "radius_miles"
        ],
        "additionalProperties": false,
        "description": "Sites within radius_miles of the centre. The count reports the centroid used and the postcodes matched.",
        "examples": [
          {
            "field": "site.location",
            "op": "within_radius",
            "centre": {
              "place": "Leeds"
            },
            "radius_miles": 20
          }
        ]
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request could not be read, or an Idempotency-Key is missing.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/idempotency-key-required",
                  "title": "An Idempotency-Key header is required",
                  "status": 400,
                  "code": "idempotency-key-required",
                  "detail": "POST /v1/orders needs an Idempotency-Key header.",
                  "next_step": "Send an Idempotency-Key header (a V4 UUID is a good choice) and reuse it on every retry.",
                  "instance": "/v1/orders"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Sign in (OAuth) or send an API key (authentication-required), or create a free account for what the anonymous tier does not cover (account-required).",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WWW-Authenticate"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/authentication-required",
                  "title": "Sign in or send an API key",
                  "status": 401,
                  "code": "authentication-required",
                  "detail": "GET /v1/orders needs a token with orders:read.",
                  "next_step": "Send Authorization: Bearer with an mdh_ API key. Sign-in through https://mydatahub.emailmovers.com/id is planned.",
                  "instance": "/v1/orders"
                }
              }
            }
          }
        }
      },
      "InsufficientCredits": {
        "description": "The balance does not cover the machine quote, which is carried here. Nothing was charged; top up on mydatahub.emailmovers.com and retry with the same quote_id.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/InsufficientCreditsProblem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/insufficient-credits",
                  "title": "Not enough credits",
                  "status": 402,
                  "code": "insufficient-credits",
                  "detail": "The machine quote needs 5,000 credits and the balance is 1,200.",
                  "next_step": "Top up at the top_up_url, then retry with the same machine quote_id (or the same enrichment request).",
                  "instance": "/v1/orders",
                  "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                  "quote": {
                    "id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                    "kind": "machine",
                    "dataset_version": "2026-W39",
                    "records": 5000,
                    "removed": {
                      "already_held": 312,
                      "suppressed": 41
                    },
                    "credits_required": 5000,
                    "credits_available": 6200,
                    "gbp_ex_vat": 1249,
                    "licence": {
                      "type": "multi_use_12m",
                      "reuse_until": "2027-09-26",
                      "resale_prohibited": true,
                      "permitted_channels": [
                        "email",
                        "telephone",
                        "post"
                      ],
                      "warranty_url": "https://emailmovers.com/trust/warranty",
                      "terms_version": "2026-09"
                    },
                    "warranty": {
                      "policy": "replace_over_threshold_hard_bounce",
                      "threshold_percent": 10,
                      "url": "https://emailmovers.com/trust/warranty"
                    },
                    "expires_at": "2026-09-27T10:14:00Z",
                    "blockers": [],
                    "organisation_id": "org_01JA0Q2V7XN3M9R6T1Y5W8ZAK8",
                    "count_id": "cnt_7K2PQ4MAXN3R6TBY5WDZ",
                    "credits_per_record": 1,
                    "balance_after": 1200,
                    "purchase": {
                      "credits_to_buy": 0,
                      "cheapest": null,
                      "gbp_ex_vat": 0,
                      "options": []
                    },
                    "signature": {
                      "alg": "ES256",
                      "kid": "qte-2026-09",
                      "jwks_url": "https://mydatahub.emailmovers.com/.well-known/jwks.json",
                      "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6InF0ZS0yMDI2LTA5In0.eyJpZCI6InF0ZV8wMUpCNE0yUjZUMVk1VzhaQUs4UTJWN1hOMyJ9.MEUCIQDexampleSignatureOnly"
                    }
                  },
                  "credits_required": 5000,
                  "credits_available": 1200,
                  "top_up_url": "https://mydatahub.emailmovers.com/billing/top-up?quote=qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The token lacks a scope (insufficient-scope, with required_scope and a WWW-Authenticate step-up challenge); no person confirmed the spend and no agent key covers it (confirmation-required, with an approval_url); an agent key's per-order cap or monthly budget does not cover it (agent-budget-exceeded); an account made by self-serve sign-up has not yet confirmed its business name and that it is a UK business, which its first order needs (business-details-required); the order needs the Data Licence and Sharing Agreement accepted at the version in force (licence-acceptance-required); or a suppression upload comes before the organisation has accepted the Article 28 data processing agreement in force (dpa-acceptance-required). Nothing is charged.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WWW-Authenticate-InsufficientScope"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/AgentBudgetProblem"
                },
                {
                  "$ref": "#/components/schemas/ConfirmationRequiredProblem"
                },
                {
                  "$ref": "#/components/schemas/Problem"
                }
              ]
            },
            "examples": {
              "confirmation": {
                "summary": "A person must confirm",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/confirmation-required",
                  "title": "A person must confirm this spend",
                  "status": 403,
                  "code": "confirmation-required",
                  "detail": "A standard API key cannot spend on its own. Nothing was charged; keep the machine quote and ask the user to approve it.",
                  "next_step": "Nothing was charged. Keep the machine quote_id and give the user the approval_url; retry with the confirmation_token it returns, or use an agent key whose limits cover the spend.",
                  "instance": "/v1/orders",
                  "action": "order",
                  "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                  "approval_url": "https://mydatahub.emailmovers.com/quotes/qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3/approve",
                  "expires_at": "2026-09-27T10:14:00Z"
                }
              },
              "budget": {
                "summary": "Agent budget exceeded",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/agent-budget-exceeded",
                  "title": "The agent key budget does not cover this spend",
                  "status": 403,
                  "code": "agent-budget-exceeded",
                  "detail": "The machine quote needs 5,000 credits; this key may spend 500 an order and has 600 left this month.",
                  "next_step": "Keep the machine quote_id and ask the key owner to approve it at approval_url, or top up at top_up_url.",
                  "instance": "/v1/orders",
                  "budget": {
                    "monthly_credits": 1000,
                    "spent": 400,
                    "remaining": 600,
                    "resets_at": "2026-10-01T00:00:00Z"
                  },
                  "per_order_max_credits": 500,
                  "quote_id": "qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3",
                  "credits_required": 5000,
                  "approval_url": "https://mydatahub.emailmovers.com/quotes/qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3/approve",
                  "top_up_url": "https://mydatahub.emailmovers.com/billing/top-up"
                }
              },
              "scope": {
                "summary": "Missing scope",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/insufficient-scope",
                  "title": "The token lacks a scope",
                  "status": 403,
                  "code": "insufficient-scope",
                  "detail": "Creating an order needs the orders:write scope.",
                  "next_step": "Ask the user to approve the scope named in required_scope, then retry.",
                  "instance": "/v1/orders",
                  "required_scope": "orders:write"
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "No such object for this organisation.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/not-found",
                  "title": "Not found",
                  "status": 404,
                  "code": "not-found",
                  "detail": "No order ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E in this organisation.",
                  "next_step": "Check the id; ids are prefixed, such as ord_ for orders and aud_ for audiences.",
                  "instance": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
                }
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "An Idempotency-Key reused with different parameters, an expired machine quote, or an object in the wrong state.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/quote-expired",
                  "title": "The machine quote has expired",
                  "status": 409,
                  "code": "quote-expired",
                  "detail": "Machine quote qte_01JB4M2R6T1Y5W8ZAK8Q2V7XN3 expired at 2026-09-27T10:14:00Z.",
                  "next_step": "Call quote_order (POST /v1/quotes) again; a machine quote is valid for 24 hours.",
                  "instance": "/v1/orders"
                }
              }
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "The request is not valid. errors lists every problem with a JSON pointer and did_you_mean.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/validation-failed",
                  "title": "The request is not valid",
                  "status": 422,
                  "detail": "Unknown field company.employees.",
                  "instance": "/v1/counts",
                  "code": "validation-failed",
                  "next_step": "Fix each entry in errors, using did_you_mean where given, and send it again.",
                  "errors": [
                    {
                      "pointer": "/audience/where/all/0/field",
                      "code": "invalid_value",
                      "message": "Unknown field company.employees.",
                      "did_you_mean": [
                        "company.employee_band"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests. Wait for Retry-After.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/rate-limited",
                  "title": "Too many requests",
                  "status": 429,
                  "code": "rate-limited",
                  "detail": "60 counts an hour per IP for anonymous callers; the next resets in 42 seconds.",
                  "next_step": "Wait for the seconds in Retry-After, then retry.",
                  "instance": "/v1/counts",
                  "retry_after_seconds": 42
                }
              }
            }
          }
        }
      },
      "ServerError": {
        "description": "Something failed on our side (500 internal-error) or the service is briefly unavailable (503 service-unavailable, with Retry-After). Nothing was charged; retry with the same Idempotency-Key. A count, sample, quote or order with telephone in play is also refused with 503 tps-screen-expired, with no Retry-After, while the dataset version's TPS and CTPS screen is more than 28 days old.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "default": {
                "summary": "Example",
                "value": {
                  "type": "https://emailmovers.com/mydatahub/docs/errors/service-unavailable",
                  "title": "The service is briefly unavailable",
                  "status": 503,
                  "code": "service-unavailable",
                  "detail": "The serving store is failing over; counts resume within a minute.",
                  "next_step": "Wait for the seconds in Retry-After, then retry with the same Idempotency-Key. The status page shows incidents.",
                  "instance": "/v1/counts",
                  "retry_after_seconds": 30
                }
              }
            }
          }
        }
      }
    },
    "parameters": {
      "MyDataHubVersion": {
        "name": "MyDataHub-Version",
        "in": "header",
        "required": false,
        "description": "The dated API version, pinned per key when left out. Non-breaking changes ship as new dates; the path major changes only for breaking changes, with a 12 month deprecation window.",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
        },
        "example": "2027-01-15"
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Makes the request safe to retry: the same key returns the stored response. Keys are kept for the life of the organisation.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "example": "6f1c3b2a-9d4e-4f8a-b1c2-7e5d9a0f3c21"
      },
      "IdempotencyKeyRequired": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Required. A retry with the same key never charges twice; a different request with the same key returns 409. Keys are kept for the life of the organisation.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "example": "6f1c3b2a-9d4e-4f8a-b1c2-7e5d9a0f3c21"
      }
    },
    "headers": {
      "RateLimit": {
        "description": "IETF RateLimit field: one item for each window that applies (counts-hourly, counts-daily, counts-per-minute or requests), each with the remaining quota (r) and the seconds to reset (t).",
        "schema": {
          "type": "string"
        },
        "example": "\"counts-hourly\";r=59;t=3522, \"counts-daily\";r=599;t=50322, \"requests\";r=119;t=42"
      },
      "RateLimit-Policy": {
        "description": "IETF RateLimit-Policy field: one item for each window that applies, each with the quota (q) and the window in seconds (w). Anonymous callers get 60 counts an hour and 600 a day per IP and fingerprint.",
        "schema": {
          "type": "string"
        },
        "example": "\"counts-hourly\";q=60;w=3600, \"counts-daily\";q=600;w=86400, \"requests\";q=120;w=60"
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer",
          "minimum": 0
        },
        "example": 42
      },
      "ETag": {
        "description": "For a count, the count id in quotes: the same definition gives the same ETag.",
        "schema": {
          "type": "string"
        },
        "example": "\"cnt_7K2PQ4MAXN3R6TBY5WDZ\""
      },
      "Location": {
        "description": "Where the new resource, or the signed file, lives: a path on https://mydatahub.emailmovers.com, resolved against the origin.",
        "schema": {
          "type": "string",
          "format": "uri-reference"
        },
        "example": "/v1/orders/ord_01JB4N9S3W2X6Y7Z8A1B2C3D4E"
      },
      "WWW-Authenticate": {
        "description": "The Bearer challenge, naming the protected resource metadata and the scopes to request.",
        "schema": {
          "type": "string"
        },
        "example": "Bearer resource_metadata=\"https://mydatahub.emailmovers.com/.well-known/oauth-protected-resource/v1\", scope=\"counts:read previews:read audiences:read\""
      },
      "WWW-Authenticate-InsufficientScope": {
        "description": "The step-up challenge on 403 insufficient-scope (RFC 6750): error=\"insufficient_scope\" with the scope to request, which MCP and OAuth clients read to ask the user, such as orders:write on the first create_order.",
        "schema": {
          "type": "string"
        },
        "example": "Bearer error=\"insufficient_scope\", scope=\"orders:write\", resource_metadata=\"https://mydatahub.emailmovers.com/.well-known/oauth-protected-resource/v1\""
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 at https://mydatahub.emailmovers.com/id, the one issuer for the app, REST and MCP: authorization code with PKCE (S256 only), rotating refresh tokens, 60 minute JWT access tokens with aud set to https://mydatahub.emailmovers.com/v1. Scopes are stepped up: the first challenge asks for counts:read previews:read audiences:read, and the first spend answers 403 insufficient_scope naming orders:write.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://mydatahub.emailmovers.com/id/authorize",
            "tokenUrl": "https://mydatahub.emailmovers.com/id/token",
            "refreshUrl": "https://mydatahub.emailmovers.com/id/token",
            "scopes": {
              "account:read": "Read the balance, plan, prices, rate limits, usage and key budgets.",
              "account:write": "Set the business name and confirm that it is a UK business (PATCH /v1/account). A signed-in owner only; admin covers it too.",
              "counts:read": "Run counts and breakdowns with the account's exact figures and New to you.",
              "previews:read": "Draw masked samples.",
              "audiences:read": "Read saved audiences.",
              "audiences:write": "Save, update, refresh and delete audiences.",
              "quotes:read": "Create and read machine quotes with the account's balance.",
              "orders:read": "Read orders, compliance receipts and CRM pushes.",
              "orders:write": "Spend credits: create and cancel orders.",
              "records:read": "Fetch and download delivered records under licence.",
              "enrich:write": "Spend credits: enrich a known contact, charged only on a confident match.",
              "suppressions:read": "Read suppression lists and check records before a send.",
              "suppressions:write": "Upload suppression lists and report objections.",
              "pushes:write": "Connect CRMs, check overlap and push delivered records.",
              "webhooks:write": "Manage webhook endpoints and read the event log.",
              "samples:request": "Ask for a sample of a counted audience, sent by email to a confirmed work address. Never returns records.",
              "admin": "Manage API keys, agent keys and the plan, including cancellation. Keys are made and changed by signed-in people only, and an agent key never holds admin."
            }
          }
        }
      },
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "mdh_live_ or mdh_test_ API key",
        "description": "An API key or agent key as Authorization: Bearer, never a custom header or query string. mdh_test_ keys return synthetic data and never charge. Keys carry scopes like OAuth tokens. A standard key never spends on its own: a spend needs a person's confirmation or an agent key within its limits."
      }
    }
  }
}
