The first A2P campaign I submitted for one of my own brands came back denied. Not for the sample messages. Not for the opt-in checkbox. It came back with a code, three words, and no explanation: disallowed content.

The content in question was not in the campaign at all. It was on the website. And that is the thing almost nobody tells you before you start: A2P 10DLC vetting is not a review of the form you filled out. It is a review of your business, using the form as the entry point. Get that backwards and you will spend weeks resubmitting a campaign that was never the problem.

This is the operator's version, written from the submissions I have run across my own sub-accounts and my clients'. What actually gets reviewed, the specific mistakes that produce each denial code, and the pass to run before you click submit.

What you are actually submitting to

Inside a GoHighLevel sub-account, registration happens under Settings, then Phone System, then the Trust Center tab. HighLevel splits it into two objects, and the distinction matters because they fail for different reasons. Per HighLevel's brand registration guide, the brand identifies who is sending the messages, and the campaign explains what types of messages you plan to send. Brand first, campaign second.

Neither one is reviewed by HighLevel. HighLevel is the interface. The submission travels to the carrier registry, and the rejection codes that come back are Twilio A2P error codes. Once you know that, the black box opens up, because Twilio publishes what every code means and whether it can be fixed with an edit. Two of the codes I have personally received in the GHL Trust Center map directly to Twilio's published catalog. When you get denied, look up the number rather than guessing at the three-word label next to it.

You will also pick a messaging tier. HighLevel's campaign registration guide puts low volume at up to 6,000 SMS segments per day and high volume at up to 600,000, and states that HighLevel applies no markup on the registry fees. Across my accounts the approved campaigns have carried an $11 per month fee. Nearly every agency sub-account I have registered belongs in low volume.

Mistake 1: assuming your agency registration covers your clients

It does not. Registration is performed inside a sub-account and is bound to the legal entity and tax ID you enter there. Your agency's approved brand covers your agency. It covers nothing else.

In practice that means every client business sending SMS from a sub-account you manage needs its own brand registration under its own legal entity, and then its own campaign under that brand. I currently maintain separate brands across three different legal entities, each in its own sub-account, each with its own approval date and its own denial history. There is no umbrella.

Plan the calendar around that. Brand approval can be quick. Campaign vetting is the slow part, and it is the part that gets denied. One client campaign of mine went from submission to approval in four days. Another took from mid March to mid April because of a denial and a full website rebuild in between. Do not promise a client that SMS goes live on their launch date until the campaign is approved, because you do not control that clock.

Mistake 2: using a name that is not the legal name

Brand registration is a records match, not a branding exercise. HighLevel's brand approval best practices are blunt about it: enter the legal company name exactly as registered with the IRS, matching the CP 575 EIN confirmation letter, and do not pull the name off a W-2 or W-9 because those can differ. The same page flags a DUNS number as unacceptable for a US standard brand, warns that address mismatches hurt your trust score, and notes that a newly issued EIN needs roughly 30 to 90 days to propagate through verification databases before it will verify.

The trap for agencies is the program name. Most of us run brands that are not registered entities. My consulting program is not its own LLC, so writing it alone as the business name would fail the records match, and writing it as a DBA would be a false statement since no DBA was ever filed. The form I use now is the legal entity followed by the program name in parentheses, and I use that exact string everywhere: the brand record, the use case description, the consent checkbox text, and the sample messages. Every place a human reviewer can compare two strings, they match.

Cheap discipline, and it removes an entire category of denial.

Mistake 3: your website denies you, not your form

This is the one that cost me a month.

My consulting brand's campaign was denied in March 2026 with Twilio error 30897, campaign vetting rejection for disallowed content. Twilio's causes for that code include third-party debt collection, credit repair, and lead generation, plus high-risk financial promotion and gambling. My campaign described appointment confirmations and follow-up for people who applied through my own form. Clean use case, clean samples.

The problem was the site. It advertised database reactivation. It said we mine your existing patient database. It had a page about lead qualification and a whole service page describing outreach we performed on a clinic's behalf. Read as a whole, that is a third-party lead generation business texting other people's contact lists, which is exactly the forbidden category. Nobody flagged a sentence for me. The campaign just came back denied.

The rebuild took a full pass over every page. Database reactivation became pre-event patient scheduling. We mine your existing patient database was deleted outright. Our scheduling assistant became your scheduling system. The most dangerous page on the site was not even linked from the navigation, and it still had to go, because it was indexed and it described the exact model that gets denied. The rule I settled on: the site has to describe tools the client operates, not outreach we perform for them. The campaign was approved in April after that rewrite.

The expensive detail is what Twilio says about recovery. Disallowed content is not an edit-and-resubmit code. Twilio's guidance is explicit that campaigns rejected for disallowed content are ineligible for resubmission, so you delete the campaign and register a new one once the underlying cause is fixed. That is why this mistake costs weeks instead of hours. Read your own public website as a hostile reviewer would before you ever open the Trust Center, especially the pages nobody links to anymore.

Mistake 4: a call to action a reviewer cannot reach

The second most common denial in my records is a message flow or call to action that could not be verified. That is Twilio error 30909, and its listed causes are all variations of the same failure: the reviewer could not see your consent flow from the outside.

Twilio names opt-in evidence that is private, behind a login, or incomplete. It names a message flow that does not list every opt-in method used for the campaign. It names website opt-in flows missing links to terms and conditions, a privacy policy, or message frequency. Every one of those is something you can check yourself in a browser window with cookies cleared.

Two operational traps live here. The first is redirects. If your site is on Cloudflare Pages with clean URLs, submitting the .html version of your opt-in page hands the reviewer a 308 redirect instead of a page. Submit the exact URL that resolves with a 200 and no hop. The second is timing: after you deploy a change to the consent page, give the CDN time to propagate before you run the compliance check, or you will fail against a cached copy of the old page and start editing content that was already correct.

My own second denial that March was this code, on a different brand, for a call to action the reviewer could not confirm. Same lesson, different account.

Mistake 5: sample messages that are templates instead of messages

Twilio's campaign troubleshooting guidance covers a cluster of sample message failures, and these are the good ones to get, because they are resubmittable with an edit.

  • Invalid sample message use case. Samples that are vague, do not match the stated campaign purpose, or never identify the brand. Every sample should name the business the same way the brand record does and should read like a message you would actually send.
  • URL shortener in a sample. Public shorteners such as bit.ly are a rejection trigger. Use a full link on your own domain, or a dedicated branded short domain you own.
  • Invalid campaign description. The guidance is to expand it so it explains who the sender is, who the recipient is, and why the messages are being sent. Treat the description as a paragraph, not a phrase.

One nuance worth flagging because it bites GHL users specifically. HighLevel's campaign guide states that sample messages cannot include custom fields or values, and Twilio's guidance is to use brackets for templated fields. GHL merge field syntax pasted straight out of a workflow is not a bracketed placeholder. I have had a submission approved that contained a raw merge field, so it is clearly not always fatal, but it is an avoidable risk. Write the samples by hand with a plain bracketed first name, and keep your STOP and HELP language in them.

Mistake 6: consent language that is technically present but structurally wrong

You can have every required phrase on the page and still fail the automated compliance check, because the check looks at where the language sits, not just whether it exists.

The structure that passed every item for me looks like this. Two separate consent checkboxes, one for transactional and one for promotional, both unchecked by default, and neither required to submit the form. The legal business name inside each checkbox label, not just in the page footer. The message type named in the checkbox itself, using the words transactional and promotional. Reply STOP to unsubscribe and Reply HELP for help inside each checkbox, not only in the paragraph underneath. Message frequency and data rate language in each checkbox. Privacy policy and terms links directly below the checkboxes. Then the supporting line: consent is not a condition of purchase, and an 18 or older statement.

Also make the phone field optional. If a phone number is required to submit the form, the consent is arguably a condition of using your service, which is the opposite of what the checkbox says.

One more thing I learned the hard way: when the automated review flips from passing to failing with no content change, that is usually caching, not your copy. Wait and re-run before you rewrite anything. Rewriting correct content because a bot hiccuped is how a two-day fix turns into a two-week fix.

The pre-submission pass

Before opening the Trust Center for any sub-account, I run this in order. It takes about half an hour and it is cheaper than a denial.

  1. Read the whole public website as a reviewer. Search it for lead generation, database reactivation, list, reactivate, and on your behalf. Include orphan pages that are still indexed but no longer in the navigation.
  2. Match the legal name to the IRS letter, character for character, and confirm the registered address matches too.
  3. Open the opt-in URL in a private window with no session. Confirm a 200 with no redirect hop, and confirm both checkboxes, the links, and the STOP language are visible without scrolling past a login.
  4. Write the use case description as a paragraph naming sender, recipient, message types, consent method, and frequency, in the same words the site uses.
  5. Hand-write two sample messages that name the brand, carry STOP and HELP, and use a bracketed placeholder rather than a merge field.
  6. Confirm no SMS workflow is live yet in the sub-account. Sending before approval is how a sub-account starts its life with a delivery problem.
  7. Save the entire submission to a file before you click submit: use case, both samples, opt-in text, every URL. If it is denied, that file is the only way to diagnose what changed.

That last one is not optional in my shop. A denial with no record of exactly what you submitted is a denial you cannot learn from, and the Trust Center does not preserve a readable copy for you.

Where automation actually helps

Let me be straight about the limits. A2P registration is not something you can automate away. There is no API that submits a brand or a campaign for you, GHL Command does not do it, and any tool claiming otherwise is describing form filling, not registration. The submission is a human writing careful sentences about a real business.

What you can automate is everything around it, and at portfolio scale that is where the hours go. Confirming the opt-in form actually exists in each sub-account and reading back the fields it collects. Checking whether any SMS workflow is already published in an account whose campaign is still pending. Pulling the custom values that hold each client's privacy and terms URLs so you are not hunting through twenty accounts by hand. Comparing a freshly built account against one you already got approved. That is the work that scales badly by clicking and scales fine when your sub-accounts are readable as data, which is the same reason a stale ID can kill a workflow action without ever showing an error.

GHL Command reaches those layers across every sub-account you manage from one place, at a flat rate that does not climb as your client list does. It will not get your campaign approved. It will tell you, before you submit, whether the account behind the campaign is actually in the state you think it is.

The denials themselves are rarely mysterious in hindsight. They are a website that describes a different business than the campaign does, a name that does not match a tax record, or a consent page a reviewer could not open. Fix those three before you submit and most of A2P stops being a lottery.

Know the state of every sub-account before you submit.

GHL Command reads forms, custom values, and workflow status across your whole GoHighLevel portfolio from Claude on your own machine, so you can verify an account is ready before a carrier reviewer decides it is not. Flat $97/mo, every sub-account included.

See how it works

Frequently asked questions

Does one A2P registration cover all my sub-accounts?
No. Registration happens inside a sub-account under Settings, Phone System, Trust Center, and it binds to the legal entity and tax ID entered there. An agency registration does not flow down. Each client business that sends SMS needs its own brand and its own campaign.

Why was my campaign rejected for disallowed content when my messages were fine?
Vetting reviews the business, not only the samples. Twilio lists third-party lead generation, debt collection, credit repair, high-risk financial promotion, and gambling among the triggers. Public website copy describing lead generation or outreach to someone else's contact list can be read as a forbidden use case even when the campaign itself reads clean.

Can I edit and resubmit a denied campaign?
It depends on the code. Twilio documents invalid campaign description, invalid sample messages, and URL shortener rejections as resubmittable through an edit. Disallowed content is not. For that one you delete the campaign and register a new one after fixing the cause.

What does a call to action not verifiable denial mean?
The reviewer could not confirm your opt-in flow from outside your organization. Usual causes are an opt-in page behind a login or on a private site, a message flow that omits one of your opt-in methods, or a consent page missing terms and privacy links or message frequency. Fix it by making the exact submitted URL publicly reachable and matching the flow you described.