An A2P SMS API is an HTTP interface your software calls to send texts from a business to people, over routes the US carriers have approved for that traffic. In the US, those routes require A2P 10DLC registration of your brand and use case, so a useful a2p sms api handles registration as well as sending.

This post is for developers who started building SMS into a product and then found out that a working POST request does not mean the text arrives. We'll cover what A2P means, why carriers filter unregistered traffic, how registration works through Ready (including checking status with GET /v1/registration), what it costs, and how long it takes. Every code sample uses the request shapes our API actually exposes. Anything beyond those is linked to the docs.

What "A2P" means, and why carriers care

A2P stands for application-to-person. It covers any text that software sends on a business's behalf: appointment reminders, shipping notices, login codes, campaign messages and replies sent from a shared inbox. The other category is P2P (person-to-person), which is you texting a friend from your phone.

Carriers treat the two differently because the risk is different. One person texting another sends a few dozen messages a day to people who know them. An application can send 50,000 identical messages in an hour to people who may never have agreed to receive them. Carrier spam filtering exists to stop that second case.

10DLC (10-digit long code) is the US system for running A2P traffic over normal local phone numbers. Before 10DLC, businesses sent from ordinary numbers and carriers guessed which traffic was legitimate. Now the business registers two things:

  • A brand: the legal entity sending, verified against its tax ID.
  • A campaign: the use case, such as account notifications or marketing, with sample messages and a description of how recipients opt in.

The numbers you send from are then attached to that registered campaign. Our 10DLC explainer covers the background in more depth.

Why unregistered traffic gets filtered

If you send A2P traffic from a 10DLC number with no registered campaign behind it, carriers will filter it. Messages may be blocked outright or dropped without notice, and the number's reputation suffers. From your app's side the API call succeeded, so the failure is easy to miss until someone mentions they never got the reminder.

Registration doesn't guarantee delivery. Content filtering still applies to registered traffic: link shorteners, wording that looks like spam, or content that doesn't match the registered use case can still get messages blocked. Registration is the requirement for being on the route at all. What you send on it is a separate question.

Registration also sets your throughput. Carriers don't publish an official rate card, so treat these as round approximations:

  • Per-second rate: about 1 to 4 segments per second for a fresh standard campaign with no vetting, and roughly 10 to 75 for higher use-case tiers.
  • T-Mobile daily brand cap: about 2,000, 10,000, 40,000, 100,000 or 200,000 messages a day, depending on trust score.
  • AT&T: throttles per second and per minute rather than applying a hard daily cap.

Picking the use case that matches what you actually send affects both approval and throughput. Our guide to matching your campaign use case to what you send explains why a reminders sender who registers as "marketing" makes things harder for themselves.

How the A2P SMS API flow works on Ready

We make Ready as a messaging API and platform for software companies that text on behalf of their own customers, as well as for businesses texting directly. The pieces are:

  1. Sub-accounts. If you're a platform, each of your customers gets a sub-account with its own numbers and its own 10DLC registration. One customer's bad list then can't damage another customer's deliverability. You create them with POST /v1/sub-accounts and list them with GET /v1/sub-accounts. Request bodies are in the docs.
  2. Registration in-app. Brand and campaign registration can be submitted through the API or in the Ready app (registration docs), not through hand-written forms to a carrier registry. MCP has no registration tools, so an AI agent can't do this step for you.
  3. Numbers. List with GET /v1/numbers and buy with POST /v1/numbers.
  4. Status check. GET /v1/registration returns where the registration stands. Your app can poll it before turning on campaign sends.
  5. Sending. POST /v1/messages sends one text, and POST /v1/messages/bulk sends the same text to many numbers.

Checking registration status

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

We won't list response fields here, because we'd rather point you at the source of truth than paraphrase it. The quickstart documents the shape. A common pattern is to run this check from a scheduled job and keep the "send campaign" button in your UI disabled until registration is approved.

Sending one text

curl -X POST https://api.tryready.com/v1/messages \
  -H "X-API-Key: $READY_API_KEY" \
  -H "Idempotency-Key: 3f2b8c1e-9a4d-4e7b-b1c2-6d5e0f9a8b7c" \
  -H "Content-Type: application/json" \
  -d '{"to": "+12125550199", "body": "Your order #1042 has shipped.", "consent_attested": true}'

A few details:

  • to is E.164. A 10-digit US number is treated as +1.
  • consent_attested: true is your promise that the recipient agreed to receive texts. We record the attestation per send (who sent, to how many, when), which builds an audit trail. It is not a per-contact consent record. Your own store needs to keep the opt-in time, wording and page URL for each contact.
  • Send an Idempotency-Key (any UUID) on every request. If your HTTP client retries after a timeout, the text won't go out twice. Without the key, retry logic can double-text people.
  • Optional fields: from (one of your numbers), media_url (for MMS) and from_strategy (local, even or random). Details are in the messages API docs.

Sending to many numbers

curl -X POST https://api.tryready.com/v1/messages/bulk \
  -H "X-API-Key: $READY_API_KEY" \
  -H "Idempotency-Key: 9c1d7e2a-4b8f-4a3e-8d6c-2f1e0b9a7c5d" \
  -H "Content-Type: application/json" \
  -d '{"to": ["+12125550199", "+15559876543"], "body": "Reminder: your appointment is tomorrow at 9 AM. Reply STOP to opt out.", "consent_attested": true}'

See the bulk messages docs for limits. For a full integration walk-through covering retries, error handling and reading messages back with GET /v1/messages, see our SMS API integration guide.

What the API does before a text leaves

The compliance work happens on our side so your code doesn't have to:

  • Opt-outs. Inbound STOP and UNSUBSCRIBE are honored automatically, and the opt-out applies across campaigns. A send to an opted-out number is refused up front and not charged. You can read opt-outs with GET /v1/opt-outs or check one number with GET /v1/opt-outs/:phone.
  • Opt-outs and numbers on your Ban list are refused up front and not charged. With landline validation on, a known landline is refused too, and the refusal bills the $0.003 check.
  • Quiet hours. A text sent during the recipient's local quiet hours is held and sent later. It is charged only when it actually sends. Campaigns, drip campaigns and automations wait up to 24 hours for the window; a one-to-one or API text is held only if the window opens within 6 hours, otherwise it is refused with 409 QUIET_HOURS_BLOCK and must be resent; a one-to-one reply to someone who texted you in the last 24 hours goes out at any hour.
  • Validation and scrubbing. GET /v1/validate/:phone checks a number, and GET /v1/scrub/:phone screens it against known TCPA-litigator and DNC-complainer lists. The standalone scrub costs $0.005 per contact.

None of this makes you immune to a TCPA claim, and compliance remains the sender's responsibility. It removes the most common ways an app ends up texting someone it shouldn't. One more rule applies: fundraising appeals and political texts need our written OK first. Email support@tryready.com before the first send and wait for our reply.

Timelines: what to expect while registration is in review

Most approvals take 2 to 7 days. Our post on how long 10DLC takes by step breaks down where that time goes. Rejections usually come down to sample messages or opt-in wording. Our guide to opt-in language that clears registration covers what reviewers look for.

You don't have to stop building while you wait:

StageWhat you can sendRate
Before registeringFirst 20 texts free (one-to-one only; a campaign is paid from the first text)Free
Before registering, after the free 20Up to 500 texts a monthNormal per-text rate
Registration in review, number already boughtSends on Ready's shared registrationSame per-text rate
RegisteredYour own brand and campaignSame per-text rate

The free texts end as soon as a registration is paid for, so use them before you register. Sending requires a card on file.

What it costs, with the math shown

The Standard rate is $0.0075/segment, plus a $0.0045 carrier fee per segment. Received replies are billed the same way as sent texts. There is one flat rate. If you're a large platform, Enterprise pricing is custom, so talk to us.

That rate excludes two optional compliance surcharges: scrubbing and landline validation. Each adds $0.003 per segment when switched on for an account, and both are off by default.

Registration has no setup fee. The charge at submit is the first month, $25. After that, the monthly cost is $25 for registration and $2 per number.

Segments are what you pay for, not messages:

  • A plain-text message fits 160 GSM-7 characters in one segment. Longer messages split into 153-character segments.
  • An emoji drops the limit to 70 characters, or 67 per segment in a multipart message.

Worked example (assumptions stated): a SaaS scheduling product sends 10,000 appointment reminders a month. Each reminder is 150 plain characters, so each is one segment. The account has one registered number.

  • Messaging: 10,000 × $0.0075 = $75, plus 10,000 × $0.0045 in carrier fees
  • Registration: $25/mo for registration and $2/mo per number after the first month
  • Throughput: at an assumed 3 segments per second, 10,000 segments take about 56 minutes to clear. That's fine for reminders spread across a day, but worth planning around if they all fire at once.

Now suppose someone adds a calendar emoji and the same 150-character message grows to 152 characters. That becomes 3 segments instead of 1, and the messaging line roughly triples. Our app swaps curly quotes, long dashes and ellipses for plain ones before sending, so those never change the count. An emoji does.

The honest comparison: raw CPaaS APIs cost less per segment. Twilio is around $0.0083/segment, and Telnyx, Plivo and Bandwidth sit at or below our rate too. If you have engineers who want to build the registration flow, sub-account isolation, opt-out handling, quiet hours and scrubbing themselves, a CPaaS is a reasonable choice. What we offer instead is self-serve registration and those compliance pieces already built, plus the inbox, contacts, campaigns and the rest of the platform. Rates are on the pricing page.

A short build checklist

  1. Create a sub-account per customer if you're a platform.
  2. Submit brand and campaign registration in-app, with a use case that matches your traffic.
  3. Buy numbers with POST /v1/numbers.
  4. Poll GET /v1/registration and gate campaign sends on approval.
  5. Send with POST /v1/messages and an Idempotency-Key on every request.
  6. Store per-contact consent in your own database, and only send consent_attested: true when you have it.
  7. Count segments before you send, especially for templates that include emoji.

FAQ

Do I need 10DLC registration to use an SMS API in the US? Yes, if you send business texts from a local 10-digit number. Carriers filter unregistered A2P traffic, so registration is effectively required for reliable delivery. On Ready, you can send up to 500 texts a month before registering, and on the shared registration while your own is in review.

How long does A2P 10DLC approval take? Most approvals take 2 to 7 days. Delays usually come from sample messages or opt-in descriptions that reviewers can't verify, so get those right on the first submission.

How do I check my 10DLC registration status through an API? Call GET /v1/registration with your X-API-Key header. The response shape is documented at docs.tryready.com, and many teams poll it to unlock campaign sends automatically once registration is approved.

What does A2P 10DLC registration cost? On Ready, there's no setup fee, and the first month ($25) is charged at submit. After that, it's $25 a month for registration and $2 a month per number.

Is an A2P SMS API the same as a CPaaS like Twilio? Not exactly. A CPaaS gives you raw sending at a lower per-segment price and leaves registration and compliance logic to you. An API like ours costs more per segment but includes registration, opt-outs, quiet hours and scrubbing.

Where to go from here

The practical takeaway: in the US, an SMS integration isn't finished when the request returns 200. It's finished when your brand and campaign are registered, your app knows the registration status, and every send carries real consent and an idempotency key. Build those pieces in from the start and you avoid finding out about filtering from your customers.

If you want to try the flow, create an account, send your free one-to-one texts before you register, and keep the quickstart open alongside your code.