Your product texts on behalf of your customers. Every customer has to be a registered brand, with a registered campaign and numbers attached to that campaign before carriers will deliver its traffic at full speed. Ten customers can be registered by hand. At a few hundred, a support person ends up copying EINs into a web form all day, and that becomes a bottleneck.

This post covers the mechanics that matter if you're automating registration as an ISV: what the brand, campaign and number-assignment steps produce, what the "tokens" are, how the pieces depend on each other, and which parts Ready exposes through its API versus handles in the app. We make Ready, so we'll also say where our API stops and where you'd be better served elsewhere.

The three objects carriers care about

A2P 10DLC registration produces three linked records. Your code has to track all of them per customer.

  1. Brand. This is the legal business sending the texts: name, EIN, address, website and contact. The brand gets an ID from the industry registry and a trust score, which sets its daily cap on T-Mobile.
  2. Campaign. This is what the brand sends and why. It covers the use case (marketing, account notifications, customer care), sample messages, the opt-in description and the opt-out language. A campaign belongs to exactly one brand and gets its own ID.
  3. Number assignment. Each sending number is linked to one campaign. A number with no campaign attached is sending unregistered traffic, and carriers filter it.

The "token" people talk about is really just the campaign ID. It's the identifier that ties a number to approved traffic. The brand ID points to the business, the campaign ID points to the use case, and the number-to-campaign link is what carriers check on every message.

The dependency order is strict: brand first, then campaign, then numbers. If a step fails, everything after it waits. A brand stuck in review means the campaign can't be submitted. A rejected campaign means numbers can't be linked.

Where developers usually trip

  • Treating approval as synchronous. Most approvals take 2 to 7 days. Your onboarding flow needs an "in review" state that persists across sessions, plus a way to re-check it.
  • One campaign for everything. If a customer sends both 2FA codes and promos, those are different use cases. Lumping them together invites filtering. Our post on why 2FA and promo traffic should be split covers that.
  • Sample messages written by engineers. A sample like "Test message {{name}}" gets rejected. If you collect samples from customers, validate them before submission. The SHAFT rejection rewrite guide shows what reviewers flag.

How Ready maps this onto sub-accounts

On Ready, each of your customers is a sub-account. A sub-account has its own numbers and its own carrier registration, so one customer's bad list can't drag down another customer's brand. That isolation is the main reason a platform wants a sub-account model instead of one shared brand for everyone. 10DLC for SaaS platforms covers the "who registers the brand" question in depth.

These are the API calls that matter for the registration lifecycle:

StepEndpointWhat it does
Create the customerPOST /v1/sub-accountsCreates an isolated sub-account for one of your customers
List customersGET /v1/sub-accountsLists the sub-accounts you manage
Buy numbersPOST /v1/numbersAdds a number to the account
List numbersGET /v1/numbersShows the numbers an account holds
Check registrationGET /v1/registrationReturns where the account's brand and campaign registration stands
SendPOST /v1/messagesSends a text from your registered number, or from a number on Ready's shared registration while yours is in review

Brand and campaign details (business info, use case, sample messages, opt-in description) can be submitted through the API or in the Ready app (see the registration docs). Ready holds the resulting brand and campaign IDs for each sub-account and links numbers to the campaign for you. You don't store or pass campaign tokens yourself. For the exact request bodies and response shapes of the sub-account, number and registration endpoints, use the reference at docs.tryready.com rather than copying fields from a blog post.

That's a deliberate tradeoff, so here it is plainly. If you want to own the raw registry objects yourself, setting the campaign ID per number and calling the registry's vetting endpoints directly, a raw CPaaS gives you that lower-level control. Ready keeps the token bookkeeping on our side so your code deals with "is this sub-account ready to send" instead of registry plumbing.

Polling registration status

Your onboarding screen needs to know when a customer goes live. A status check looks like this:

curl https://api.tryready.com/v1/registration \
  -H "X-API-Key: $READY_API_KEY"

Run this on a schedule (a few times a day is plenty, given 2-to-7-day reviews). Update your own customer record when the status changes. Surface rejections to the customer with the reason instead of leaving them on a spinner.

What your customers can do while registration is in review

The 2-to-7-day wait is where most platforms lose customers during onboarding. Ready has three things that soften it:

  • The first 20 texts are free. They're one-to-one sends, not campaigns. Use them before registering, because the free texts end the moment a registration is paid for.
  • Up to 500 texts a month before registering, at the account's normal per-text rate. Past that, the account has to register.
  • Shared registration during review. If an account bought its number before registering, it sends on Ready's shared registration at the same per-text rate while its own registration is in review.

To send, you add a card and get a number, which is $2 a month with the first month charged when you get it. In practice, your onboarding can let a new customer send real one-to-one texts on day one, so they're not blocked for a week. Our post on sending before 10DLC clears goes further on this.

Sending once registered

When the status check says the campaign is approved, sending is a single call. Always include an Idempotency-Key so a retry after a timeout doesn't double-send:

curl -X POST https://api.tryready.com/v1/messages \
  -H "X-API-Key: $READY_API_KEY" \
  -H "Idempotency-Key: 6f1c2a9e-4b7d-4e2f-9a31-0c8d5e7b1f22" \
  -H "Content-Type: application/json" \
  -d '{"to": "+12125550199", "body": "Your order #1042 has shipped.", "consent_attested": true}'

consent_attested is your promise that the recipient agreed to texts. Ready records the attestation (who sent, to how many, when) as an audit trail of the send. It isn't a per-contact consent record. The opt-in time, wording and page URL for each recipient have to live in your own database.

For lists, POST /v1/messages/bulk takes up to 100 recipients per call, so batch larger lists. Opt-outs and numbers on your Ban list are refused up front and not charged. A text that lands in the recipient's quiet hours is held only if their window opens within 6 hours, and it's charged only when it actually sends. Otherwise that recipient comes back with a 409 QUIET_HOURS_BLOCK line and is not sent, so send it again once the window opens. Full shapes are in the messages docs and bulk docs.

Throughput after approval

Approval doesn't mean unlimited speed. A fresh standard campaign with no vetting typically runs around 1 to 4 segments per second, and the T-Mobile daily cap ranges from roughly 2,000 to 200,000 messages depending on brand trust score. Treat these as approximations, since carriers don't publish a rate card. At an assumed 2 segments per second, a 10,000-segment send takes about 83 minutes. Build your queue to expect that.

The money: what automating 50 registrations costs

Registration has no setup fee. At submit, the account is charged the first month, $25. After that the monthly cost is $25/mo for registration + $2/mo per number.

Here's a worked example. Assume a platform onboards 50 customers, each with one brand, one campaign and one number:

  • Monthly registration: the brand, campaign and number fees, repeated for each of the 50 customers
  • Sending: say each customer sends 2,000 single-segment texts a month = 100,000 segments, at $0.0075 + $0.0045 per segment. That's 100,000 × ($0.0075 + $0.0045), all-in excluding the compliance surcharge.

Ready's all-in prices per segment include the carrier fee but not screening: Scrub lists and Number validation, the two switches in Settings under Compliance, each add $0.003 per segment when switched on, shown as screening on your bill, and both are off by default. Unless you turn the opt-out footer off, the first text to each contact, and one again from time to time, also gets "Reply STOP to opt out" and your business name if the message does not already have them, so a text close to the segment limit can bill one more segment.

The fixed $27 per customer is the number to price into your plans, because it's owed whether that customer sends one text or ten thousand. How SaaS platforms should price 10DLC into every plan works through the margin side.

On per-segment price, be honest with yourself. Twilio sits around $0.0083 per segment and GoHighLevel/LeadConnector around $0.0083 per message, both lower than the Standard rate. If your team is comfortable building its own registry integration, status polling, opt-out store and quiet-hours logic, raw CPaaS is the lower bill. What you get on Ready is the in-app registration flow, per-sub-account isolation, STOP handling, quiet-hours holds and optional litigator scrubbing already built. Many platforms find that worth more than the per-segment difference.

What the API doesn't do (yet)

  • Brand and campaign registration can be submitted through the API or in the Ready app. The request bodies are in the registration docs, not in this post.
  • The MCP server at api.tryready.com/mcp has no tools for buying numbers or registering, so AI agents can send and manage contacts but can't onboard brands.
  • Brand vetting ($79 Standard / $179 Enhanced, one-time) is optional. It only matters if a customer's volume hits the daily cap.

The practical takeaway

Model registration as a three-step, asynchronous pipeline: brand, then campaign, then numbers. Store a status per customer and poll it. Don't block onboarding on approval. On Ready, the sub-account is your unit of isolation, the campaign token lives on our side, and your code mostly needs POST /v1/sub-accounts, GET /v1/registration and POST /v1/messages.

If you want to try the flow end to end, the quickstart walks through a first send, and you can create an account and use your 20 free one-to-one texts before you submit a registration. For the platform-level view of the same process, see the 10DLC registration API overview.