{
  "id": "CMP-014",
  "slug": "cmp-014",
  "title": "Keyword entries must carry no surrounding whitespace",
  "statement": "Keyword lists must be comma-separated with no space around the individual entries.",
  "rationale": "Keyword lists are stored as one comma-delimited string and split back apart without trimming, so a space typed after a comma becomes part of the next keyword — and \" STOP\" is not STOP. The consumer texts the word on your signage, the match fails, and the opt-out that everyone believes is configured never fires.",
  "layer": "CAMPAIGN",
  "layerSlug": "campaign",
  "object": "campaign.optin_keywords + optout_keywords + help_keywords",
  "severity": "MEDIUM",
  "detectability": [
    "DETERMINISTIC"
  ],
  "failureClass": "RETRY_FIELD",
  "authorities": [
    "Plivo",
    "Bandwidth",
    "TCR",
    "Telnyx"
  ],
  "codes": [
    {
      "provider": "TCR",
      "code": "501",
      "remediable": true
    }
  ],
  "applicabilityText": "Applies to every 10DLC registration.",
  "universal": true,
  "remediation": "Retype the lists with commas and no spaces, or trim each entry if you are building the string in code. Done when no keyword begins or ends with a space — which you can only see by selecting the text, so check it in code rather than by eye.",
  "example": "optout_keywords: STOP,QUIT,END,REVOKE,OPTOUT,CANCEL,UNSUBSCRIBE",
  "notes": "A space INSIDE a keyword is a different defect with a different fix and belongs to CMP-KEYWORD-FMT, which rejects the whole token as non-alphanumeric. This rule is only about padding introduced by splitting the delimited string, so the two do not report the same list twice.",
  "phase": "approval",
  "automated": true,
  "url": "https://ekas.io/rules/10dlc/campaign/cmp-014/",
  "markdown": "https://ekas.io/rules/10dlc/campaign/cmp-014.md",
  "registry": "https://ekas.io/rules/10dlc/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/"
}
