TLDR: 30908 privacy policy can't be verified is almost never about your privacy page wording. It's about whether a human vetter can physically reach your opt-in flow and see the policy at the point of consent.

What We Built

I shipped a real-time labor and delivery SMS notification app in one autonomous session — a Next.js app that sends real-time SMS updates to family during labor and delivery.

The SMS layer is standard A2P stuff: Twilio (the cloud messaging platform), webhooks, STOP/START inbound sync. Phase 4 was the full engine. By June 18 it was wired and deployed.

Next step: 10DLC campaign registration — the US carrier requirement that every business sending SMS must complete or your messages get blocked.

The Rejection

Three errors. All at once.

  • 30886 — campaign description too thin/generic
  • 30893 — sample message content invalid
  • 30908 — privacy policy can't be verified

My immediate read on 30908? The privacy page wording is wrong.

It wasn't.

The /privacy page was live. It was real — what data we collect, that we don't sell it, that it's not used for marketing. The URL was linked in the submission. I rewrote the wording. Resubmitted.

Rejected again.

The Actual Problem

Here's what I didn't understand until I sat with it: 30908 is almost never about your privacy page text.

It's about whether the vetter — an actual human being — can reach your opt-in/consent flow and verify the privacy disclosure at the moment of signup.

Our recipient signup was gated behind a per-event invite token and a password. The vetter couldn't get in. Couldn't see the opt-in. Couldn't verify the policy at the point of consent.

So… rewriting the page? Totally the wrong fix.

The real fix: build a public /messaging program page — always reachable, no login, no token — with the program description, who sends, what they'll receive, and the opt-in language. Something any carrier rep (or any recipient) can read at any time.

The Other Two

30886 — thin description.

"Sends birth updates to family" is not a campaign description, apparently. The fix: name who sends, who receives, why, that it's NOT marketing, and link the public program page. Be explicit enough that a stranger with no context understands the use case.

30893 — sample content.

This one was subtle, and honestly kind of painful.

I had prefixed every outbound SMS with Baby [Last Name]: — warm, personal, exactly right for the moment.

Carriers read that as person-to-person traffic. Not A2P. Rejected under 30893.

The rule: samples must self-identify the registered program name, and they must match your real outbound byte-for-byte. Don't add a Reply STOP footer in the submission if your code never sends one.

Before:

Baby [Last Name]: She's in active labor! Updates coming soon. 💙

After:

Birth Updates [Program Name]: Active labor has started! Updates coming. Reply STOP to opt out.

It's a different feel. But it's what passes.

Why This Matters

Every builder I've seen hit 30908 chases the fix in the wrong place — rewrites the privacy policy, reformats the bullets, swaps "will not" for "never."

That's not the problem.

The question isn't "does my policy say the right things?"

It's: "Can the vetter walk through my opt-in flow, unauthenticated, and see my privacy disclosure at the exact point of consent?"

If that flow is token-gated or password-locked — they can't. And you'll keep getting rejected no matter how good the wording is.

Build the public program page. Make the opt-in path reachable without authentication. Prefix your SMS with the registered program name. Write the campaign description for a stranger.

That's the whole fix.