10DLC Rejected for 'SHAFT'? The Sample-Message Rewrite That Passes
You filled out the campaign form, hit submit, waited two days, and got back a one-line rejection that says something like "Content violates SHAFT policy" or "Sample message does not match campaign use case." No edit suggestions. No highlighted offending word. Just a wall and a resubmit button.
Full disclosure: I work for ReadySMS, and we run brand and campaign registration in-app, so I've watched a lot of these come back. The good news is that the rejection vocabulary is small. Maybe five reasons cover 90% of what gets bounced. Once you can read the code, the fix is usually a 10-minute rewrite of your sample messages — not a fundamental problem with your business.
Here's how to decode each one and what the passing version looks like.
First, what the reviewer is actually doing
A human (or a model doing a first pass, then a human) compares three things on your campaign:
- The use case you declared (marketing, customer care, 2FA, mixed).
- The sample messages you pasted in.
- The opt-in description / call-to-action you wrote out.
They reject when those three don't agree, or when a sample contains content from a prohibited category. They are not reading your website. They are not assuming good intent. If your sample says "🔥 50% OFF EVERYTHING" and your use case says "appointment reminders," that's a mismatch and it bounces.
So most rejections are really one of two failures: a content violation (SHAFT) or a consistency failure (the three things don't line up). Let's take them in order of how often they show up.
SHAFT: the content categories that auto-bounce
SHAFT stands for Sex, Hate, Alcohol, Firearms, Tobacco — plus cannabis, which gets lumped in even where it's legal. Carriers screen for these regardless of whether your business is legitimate.
The trap: you don't have to be selling any of these to trip it. A wine bar, a cigar lounge, a dispensary, a gun range, even a med spa using the wrong word — all get caught. The reviewer reads the words in your sample message, not your incorporation papers.
Before (rejected — alcohol):
"Happy hour starts at 5! $3 beers and half-price margaritas all night. Reply STOP to opt out."
After (approved — same business, no SHAFT trigger):
"Your table for 2 is confirmed for Fri 7PM at Maple & Vine. Reply C to confirm or R to reschedule. Reply STOP to opt out."
Notice what changed: the second version reframes the campaign as reservations and reminders rather than promoting alcohol. If alcohol promotion is genuinely your use case, you'll need an age-gated opt-in and you should expect tighter scrutiny — but most hospitality businesses don't actually need to advertise drink specials over SMS. Sell the reservation, not the margarita.
A few quick SHAFT-adjacent words that get flagged even in innocent contexts: "shot" (firearms/alcohol), "vape," "CBD," "kratom," and anything implying age-restricted purchase. If you don't need them in the sample, cut them.
Sample / CTA mismatch: the silent majority of rejections
This is the one nobody warns you about. Your samples have to be representative of every kind of message you'll send, and they have to match the use case and opt-in you described.
Common mismatch patterns:
- Use case says 2FA / account notifications, sample is a promo. Reject.
- Use case says customer care, samples are all outbound marketing blasts. Reject.
- Opt-in description says "customers text JOIN to a keyword," but the sample reads like a cold message to a purchased list. Reject — and rightly so.
Before (rejected — mixed use case, single sample):
Use case: Mixed
Sample 1: "Don't miss our Memorial Day sale — 40% off sitewide!"
One promotional sample for a "mixed" campaign tells the reviewer nothing about your transactional traffic. Give them coverage.
After (approved — three samples covering the real traffic):
Sample 1: "Acme: Your order #4821 has shipped. Track it: acme.co/t/4821. Reply STOP to opt out."
Sample 2: "Acme: Spring sale — 20% off, code SPRING. Shop: acme.co/sale. Reply STOP to opt out."
Sample 3: "Acme: Your verification code is 558102. It expires in 10 min."
Three samples, each mapping to a slice of the declared traffic, each with the brand name. That's what "representative" means. If you're an ecommerce sender, our 10DLC compliance guide for e-commerce walks through exactly which message types to declare.
Missing opt-in language and consent description
Carriers want to see, in plain words, how a person ends up on your list. "Customers gave us their number" is not an opt-in description. They want the mechanism.
A passing opt-in description names:
- Where the number is collected (website form, keyword, point of sale, checkout checkbox)
- What the person agrees to (message frequency, that data rates apply)
- That consent isn't required to purchase (if it's marketing)
Before (rejected):
"We text customers who have signed up."
After (approved):
"Customers opt in by checking an unchecked box at checkout on acme.co that reads: 'Yes, send me order updates and offers by text. Msg & data rates apply. Msg frequency varies. Reply STOP to cancel, HELP for help. Consent not required to purchase.' A screenshot of the form is available."
The phrase "unchecked box" matters — pre-checked consent is a non-starter. If your opt-in is a keyword, describe the keyword and the confirmation reply. The SMS keyword campaigns post covers how to build that funnel so it both converts and survives review.
Sample messages missing the required boilerplate
Reviewers expect to see consent mechanics inside the sample text itself, not just in your description. At minimum, your samples should demonstrate:
- Brand identification — who the message is from
- STOP language on at least one sample (typically the first/marketing one)
- HELP language somewhere in your set
Here's a quick checklist of what a clean sample set contains:
| Element | Where it goes | Example |
|---|---|---|
| Brand name | Start of message | "Acme:" |
| Opt-out | At least one sample | "Reply STOP to cancel" |
| Help | At least one sample | "Reply HELP for help" |
| Real link format | If you use links | acme.co/sale, not bit.ly/xyz |
| Frequency note | Marketing opt-in description | "Msg frequency varies" |
That link row is doing quiet work. Public URL shorteners get filtered at the carrier level even after your campaign is approved, which is a separate headache from registration — we wrote up the branded-domain fix for shortener filtering if you're leaning on bit.ly today.
Vague brand info and EIN mismatches
This one rejects at the brand layer, before the campaign even gets read. The business name, EIN, and address you submit have to match IRS records exactly. "Acme LLC" vs "Acme, LLC" vs the DBA you actually trade under is enough to fail vetting.
Fixes that work:
- Pull your exact legal name and EIN from your IRS CP-575 or SS-4 letter, not from memory.
- Use a sole proprietor registration path if you don't have an EIN — it exists specifically for that.
- Match the address to what's on file with the IRS.
If you're a GHL agency registering on behalf of many clients, each client's brand has to be its own truthful entity — you can't blanket-register them under your agency. The complete GoHighLevel 10DLC registration guide breaks down the per-location approach so sub-accounts stay isolated and approvable.
How to catch these before you submit
The whole point of running registration inside the platform that also sends your messages is that the same failures get caught earlier. In ReadySMS, brand and campaign registration is handled in-app — roughly ~$10/mo per brand and ~$20/mo per campaign in carrier fees, with approval typically landing in 1–3 days. Because the form, the samples, and the live sending all live in one place, the obvious mismatches (a promo sample under a 2FA use case, a sample with no STOP language) are visible before you ever spend a registration cycle on a rejection.
A pre-submit self-review I'd run on any campaign:
- Read your use case out loud. Now read each sample. Do they describe the same business doing the same thing?
- Scan every sample for SHAFT words. Cut any you don't strictly need.
- Confirm at least one sample has STOP and one has HELP.
- Confirm your opt-in description names the mechanism, not just the intent.
- Confirm brand name + EIN + address match the IRS letter character-for-character.
If all five pass, you've eliminated the reasons behind the vast majority of rejections.
The practical takeaway
10DLC rejections feel personal because the feedback is so thin, but they're almost always one of five mechanical problems: a SHAFT word, a sample that doesn't match the use case, weak opt-in language, missing STOP/HELP boilerplate, or a brand-info mismatch. None of them require changing your business — just rewriting what you pasted into the form.
Rewrite the samples to describe the traffic you'll actually send, put the consent mechanics in plain words, and check your legal name against the IRS letter. If you'd rather not do the resubmit dance at all, you can run brand and campaign registration directly in ReadySMS and see the gaps before you submit — and there are 2,500 free credits to test sends once you're approved. For the deeper background on how the whole regime fits together, the operator-grade 10DLC guide is the next thing worth reading.