{
  "id": "MSG-296",
  "slug": "msg-296",
  "title": "Platform sample specifications must be met where an ISV imposes one",
  "statement": "Where the campaign is registered through an ISV that publishes its own sample specification, the samples must satisfy it — for HubSpot, exactly two samples, each carrying the business name, opt-out instructions including STOP, a privacy-policy link, and bracketed personalisation.",
  "rationale": "An ISV sits between the business and TCR and applies its own acceptance rules first, so a submission that would clear every carrier requirement is still rejected at the platform without ever reaching a carrier. HubSpot publishes the strictest sample specification found anywhere — a superset of what any carrier asks — and businesses meet the carrier bar, submit, and are refused by their own tooling with no reference to a carrier rule they can look up. It is worth stating separately because the fix is cheap and the confusion is expensive: nothing is wrong with the campaign, only with the shape of it for one route.",
  "layer": "MESSAGE_CONTENT",
  "layerSlug": "message-content",
  "object": "campaign.sample[]",
  "severity": "BLOCKING",
  "detectability": [
    "DETERMINISTIC"
  ],
  "failureClass": "RETRY_FIELD",
  "authorities": [
    "HubSpot"
  ],
  "applicability": {
    "providers": [
      "HUBSPOT"
    ]
  },
  "applicabilityText": "Applies when the submission target is HUBSPOT.",
  "universal": false,
  "remediation": "Submit exactly two samples and put all four elements in each: the business name at the front, \"Reply STOP to opt out\", a link to your public privacy policy, and at least one [bracketed] personalisation token. Done when both samples carry all four — HubSpot checks each sample independently rather than the set as a whole.",
  "example": "sample1: \"Acme Coffee: hi [first name], 20% off all espresso blends this weekend. Privacy: https://acmecoffee.com/privacy Reply STOP to opt out.\"\nsample2: \"Acme Coffee: hi [first name], order [order number] is ready for pickup. Privacy: https://acmecoffee.com/privacy Reply STOP to opt out.\"",
  "pitfalls": [
    "The privacy policy behind the link has to carry the mobile-information non-sharing statement and the rates disclosure — a link to a generic generated policy satisfies this rule and is then rejected on the policy itself."
  ],
  "notes": "Provider-tagged rather than applied as a superset, and that is the whole point of the tag here: this is one vendor's contract, not a carrier requirement, so imposing it on everyone would fail compliant registrations for not doing something no carrier asks. The check returns UNCLEAR while the submission target is unknown, because \"we do not know which platform you are using\" is the honest answer and returning a vacuous PASS would hide the requirement from the users who owe it. Source: aws-and-resellers.md section A, HUBSPOT-REG.",
  "phase": "approval",
  "automated": true,
  "url": "https://ekas.io/rules/10dlc/message-content/msg-296/",
  "markdown": "https://ekas.io/rules/10dlc/message-content/msg-296.md",
  "registry": "https://ekas.io/rules/10dlc/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/"
}
