SMS agent quickstart

This is the shortest path from zero to a sent message over MCP. There are two compliance paths; toll-free is the fastest and the recommended default (one form, no fees, no brand/campaign). Pick 10DLC only when you specifically need local numbers or higher throughput.

Whatever path you take, get_sms_setup_status is the source of truth. After every step, call it: it returns the unified state, the reason for any hold, the concrete fix, the exact next tool to call, and canSend (whether production sends are allowed yet). Poll it while approvals are pending — don’t guess from individual objects.

All SMS tools return sms_unavailable when Telnyx isn’t configured on the platform. Role gates match the REST surface: buying numbers and compliance submissions need manage (owner/admin); wiring and sending need developer+.

Path A — Toll-free (fastest, free)

purchase_phone_number(numberType: "toll_free")
  → submit_tollfree_verification
  → poll get_sms_setup_status  until canSend == true
  → send_sms
  1. Buy the number.

    { "name": "purchase_phone_number",
      "arguments": { "e164": "+18445550123", "numberType": "toll_free" } }
    

    If the cost is over your approval threshold (or you’re not an owner), you get an approvalUrl instead — surface it and wait for approval, then the purchase completes.

  2. Submit the verification. One form: business + contact details, the numbers to verify, use case, sample/production message content, the opt-in workflow plus at least one opt-in evidence URL, and message volume. Full state name ("California", not "CA") and a non-empty additionalInformation are required quirks — the tool validates locally and returns errors if anything is missing, so fix and resubmit for free.

    { "name": "submit_tollfree_verification",
      "arguments": { "phoneNumbers": ["+18445550123"], "businessName": "…",
        "useCase": "…", "optInWorkflowImageUrls": ["https://…/optin.png"],
        "messageVolume": "…", "additionalInformation": "…" } }
    
  3. Poll status. get_sms_setup_status(numberId) moves pending_review → approved. Typical turnaround ≈5 business days. Resubmission is free and unlimited (except a terminal “High Risk - Fraud” rejection).

  4. Send. Once canSend is true, send_sms. While still pending you may send limited traffic with allowPending: true (throttled — expect a warning).

Path B — 10DLC local

register_sms_brand
  → (sole-prop only) confirm_sms_brand_otp
  → create_sms_campaign        ← $15 per submission — validate first
  → assign_number_to_campaign
  → poll get_sms_setup_status  until canSend == true
  → send_sms
  1. Register the brand (once per org — the org’s legal identity).

    • Standard: entityType (e.g. PRIVATE_PROFIT) + companyName + ein (matching IRS records) + address. Approval is ~instant.
    • Sole proprietor: entityType: "SOLE_PROPRIETOR", no EIN — firstName/lastName + mobilePhone. The response has otpRequired: true; a PIN is texted to that mobile (expires in 24 h). Caps: 1 campaign, 1 number, ~1,000 msgs/day.
    { "name": "register_sms_brand",
      "arguments": { "entityType": "PRIVATE_PROFIT", "displayName": "Acme",
        "companyName": "Acme Inc", "ein": "12-3456789" } }
    
  2. Confirm the OTP (sole-prop only):

    { "name": "confirm_sms_brand_otp", "arguments": { "brandId": "…", "pin": "123456" } }
    

    If Telnyx can’t automate this, the status degrades to action_required with instructions rather than blocking — check get_sms_setup_status.

  3. Create the campaign — mind the $15. Each create_sms_campaign submission (and every resubmission) costs $15. The tool validates the whole payload locally first and returns errors with no charge if anything fails TCR rules — never spend money on a payload you haven’t cleared. Over your approval threshold it returns an approvalUrl; the charge happens on approval.

    { "name": "create_sms_campaign",
      "arguments": { "brandId": "…", "usecase": "…", "description": "…",
        "sampleMessages": ["…"], "messageFlow": "…" } }
    

    Fix any errors, resubmit, and only then let it charge.

  4. Assign the number. assign_number_to_campaign(campaignId, numberId) — enforces the 49-numbers-per-campaign T-Mobile cap.

  5. Poll status. get_sms_setup_status walks TCR review → per-carrier MNO review (T-Mobile ≤24 h; AT&T/Verizon 1–3 business days).

  6. Send once canSend is true.

Wire it into an app

Once a number can send, attach it to a service to inject the SMS_API_* env vars and let the app send/receive on its own:

{ "name": "attach_phone_number_to_service", "arguments": { "numberId": "…", "serviceId": "…" } }
{ "name": "set_sms_inbound_webhook", "arguments": { "numberId": "…", "url": "https://app.example.com/sms/inbound" } }

See the SMS & phone numbers guide for the SMS_* env contract, the send API, and inbound signature verification.

Cheat sheet

  • Start and re-check with get_sms_setup_status — it names the next tool and tells you canSend.
  • Toll-free is fastest and free. Prefer it unless you need local presence / higher throughput.
  • 10DLC campaigns cost $15 per submission. The tool validates locally first — never submit a payload with errors.
  • Sends are blocked until compliance is approved; the send error carries the setupStatus so you know why.