{
  "id": "CMP-096",
  "slug": "cmp-096",
  "title": "Keyword opt-in requires both the keywords and the confirmation text",
  "statement": "A keyword-based opt-in must populate both the opt-in keywords and the opt-in confirmation message.",
  "rationale": "The keyword is how the consumer joins and the confirmation is what tells them they succeeded; a keyword programme with no confirmation leaves them texting into silence, then texting again. Providers check the pair together because either alone is an incomplete programme.",
  "layer": "CAMPAIGN",
  "layerSlug": "campaign",
  "object": "campaign.optin_keywords + campaign.optin_message",
  "severity": "BLOCKING",
  "detectability": [
    "DETERMINISTIC"
  ],
  "failureClass": "RETRY_FIELD",
  "authorities": [
    "TCR",
    "Twilio",
    "Bandwidth",
    "AWS"
  ],
  "applicability": {
    "consentMethods": [
      "keyword"
    ]
  },
  "applicabilityText": "Applies when consent was collected by text-to-join keyword.",
  "universal": false,
  "remediation": "Populate campaign.optin_keywords with the keyword your signage advertises, and write the confirmation message carrying brand, frequency, rates, HELP and STOP. Done when texting the keyword would produce that exact reply.",
  "example": "optin_keywords: JOIN, START · optin_message: \"Acme Coffee: you're subscribed to offers. Msg frequency varies. Msg & data rates may apply. Reply HELP for help, STOP to cancel.\"",
  "pitfalls": [
    "The keyword in the campaign must match the keyword on the signage exactly — JOIN and JOINUS are different programmes to a reviewer comparing the two."
  ],
  "catalogIds": [
    "CMP-196"
  ],
  "phase": "approval",
  "automated": true,
  "url": "https://ekas.io/rules/10dlc/campaign/cmp-096/",
  "markdown": "https://ekas.io/rules/10dlc/campaign/cmp-096.md",
  "registry": "https://ekas.io/rules/10dlc/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/"
}
