Skip to content

Developer docs

SMS for your agent, four ways.

AI Text-a-roo is an SMS gateway for AI agents. Your agent talks to it over a remote MCP server, a REST API, a Python SDK or a local bridge, always over outbound HTTPS, so there's no webhook to host and no public IP to expose.

Quickstart

Sign up, text yourself, and wait for your reply. The only manual step is reading the 6-digit code from your phone.

Terminal
# 1. Text a verification code to your phone
curl -X POST https://api.aitextaroo.com/v1/auth/verify \
  -H "Content-Type: application/json" -d '{"phone": "+12125551234"}'

# 2. Confirm it and get an API key (label names it) + your AI's number
curl -X POST https://api.aitextaroo.com/v1/auth/confirm \
  -H "Content-Type: application/json" -d '{"phone": "+12125551234", "code": "123456", "label": "My agent"}'

# 3. Text yourself
curl -X POST https://api.aitextaroo.com/v1/send \
  -H "Authorization: Bearer $AITEXTAROO_API_KEY" \
  -H "Content-Type: application/json" -d '{"text": "Hello from my agent!"}'

# 4. Wait for your reply
curl -X POST https://api.aitextaroo.com/v1/messages/wait \
  -H "Authorization: Bearer $AITEXTAROO_API_KEY" \
  -H "Content-Type: application/json" -d '{"timeout_seconds": 60}'

MCP server

The remote MCP server at https://api.aitextaroo.com/mcp (streamable HTTP) works with Claude, ChatGPT, Grok Bot, Claude Code, Codex, Cursor and any MCP client. Sign in with your phone through OAuth, or send Authorization: Bearer <API key>.

  • send_textText the owner
  • wait_for_replyWait for a reply
  • get_recent_messagesRecent texts
  • text_contactText a contact (Pro)
  • verify_pinVerify the owner's PIN
  • set_pinSet or change the PIN
  • get_accountAccount and usage
  • get_upgrade_linkPro upgrade link
  • set_webhookForward texts to a webhook
  • remove_webhookStop forwarding
  • list_connectionsWhat's connected
  • remove_connectionDisconnect a key or app
  • get_helpHow it works
Full MCP reference and client setup →

Agent Skill

The AI Text-a-roo skill is a standard Agent Skill (a SKILL.md with references and a dependency-free Python helper). It teaches your agent how to set you up, when a text is worth sending, how to wait for replies, and when to ask for your PIN.

Read it at /skills/aitextaroo/SKILL.md or download aitextaroo-skill.zip.

Claude and Claude Duet

Download the ZIP, then upload it under Customize → Skills.

Copy
https://aitextaroo.com/skills/aitextaroo.zip

Claude Code

Install the plugin, which bundles the skill and the MCP server (in a session):

Copy
/plugin marketplace add rwfresh/aitextaroo-clients
/plugin install aitextaroo@aitextaroo

Codex

Install the plugin, which bundles the skill and the MCP server:

Copy
codex plugin marketplace add rwfresh/aitextaroo-clients
codex plugin add aitextaroo@aitextaroo

Gemini CLI

Install the extension:

Copy
gemini extensions install https://github.com/rwfresh/aitextaroo-clients

Cursor, Muse Code and other Agent Skills clients

Add it with the skills CLI, or unzip into your agent's skills folder (for example .agents/skills/ in a project):

Copy
npx skills add rwfresh/aitextaroo-clients
# or
curl -sSL https://aitextaroo.com/skills/aitextaroo.zip -o /tmp/aitextaroo-skill.zip
unzip -o /tmp/aitextaroo-skill.zip -d .agents/skills

Grok Bot

Ask it to create a skill from the instructions:

Copy
Create a skill from https://aitextaroo.com/skills/aitextaroo/SKILL.md

REST API

Base URL https://api.aitextaroo.com/v1. JSON in, JSON out. Authenticated endpoints take Authorization: Bearer <API key>. Machine-readable spec: openapi.json.

AI Text-a-roo REST endpoints
MethodPathKeyWhat it does
POST/v1/auth/verifynoText a 6-digit code to a phone: {"phone": "+1…"}
POST/v1/auth/confirmnoConfirm the code and add a key: {"phone", "code", "label"} (label optional). Returns api_key, key_id, assigned_number, tier, and retired (any key removed to stay at the limit). Other keys and app sign-ins keep working
POST/v1/sendyesText the owner {"text"}, or a contact on Pro {"text", "to", "recipient_name"}
POST/v1/messages/waityesWait up to 120 s for the owner's next text: {"timeout_seconds": 60}
GET/v1/messages/recentyesTexts from the last five minutes (?after_id= cursor)
GET/v1/streamyesServer-Sent Events stream of inbound texts (Last-Event-ID replay)
POST/v1/webhookyesForward inbound texts to a URL: {"url", "auth_header", "pin"}. The PIN is required if one is set; the owner is texted first
DELETE/v1/webhookyesStop webhook delivery (the owner is texted)
GET/v1/accountyesPlan, AI number, PIN status, usage and daily limit
POST/v1/verify-pinyesCheck a PIN the owner texted: {"pin"}
POST/v1/account/pinyesSet the owner's PIN {"pin"}, or change it {"pin", "current_pin"}. The owner is texted first
DELETE/v1/account/pinyesRemove the PIN: {"current_pin"}. The owner is texted first
GET/v1/account/connectionsyesKeys and app sign-ins on the account, which one is the caller (current), and which one set up forwarding
DELETE/v1/account/connections/{connection_id}yesDisconnect a key or app sign-in: {"pin"} if one is set. The owner is texted; forwarding it set up stops too
POST/v1/billing/checkoutyesStripe checkout link for Pro
POST/v1/billing/portalyesStripe portal link to manage or cancel

Keys & connections

Each new key is added next to the others, with a name: from aitextaroo-setup, the dashboard's Create a new key, or POST /v1/auth/confirm with an optional label (up to 40 letters, digits, spaces and . _ ( ) ' @ # : + -). The account's other keys and app sign-ins keep working. An account holds up to 10 keys: adding one more removes the key unused the longest, keeping the one that set up forwarding when it can, and POST /v1/auth/confirm lists it in retired. The owner is texted whenever a key is added or an app signs in.

GET /v1/account/connections (MCP: list_connections) lists the keys and app sign-ins, marks the caller as current, and shows which one set up forwarding. DELETE /v1/account/connections/{connection_id} (MCP: remove_connection) disconnects one right away: it needs the owner's PIN when one is set, stops the forwarding that connection set up, and texts the owner. On the dashboard, the owner can remove any connection, stop forwarding, set or remove the PIN, or sign out everything at once.

Receiving texts

Each text the owner sends goes to exactly one place, in this order:

  1. A waiting wait_for_reply MCP call or POST /v1/messages/wait.
  2. Otherwise, the live GET /v1/stream connection (that's what the bridge uses), and your webhook if you registered one.
  3. Otherwise, it waits in memory for up to five minutes, readable with get_recent_messages.

So an agent that only runs while you chat with it won't see texts you send at other times unless a webhook is registered. Cloud agents can register one themselves with the set_webhook MCP tool, for example a Grok Bot webhook routine, so every text starts a run.

Webhook deliveries are signed: the X-Signature header is a hex HMAC-SHA256 of the raw body, keyed with the secret returned when you registered. If you set auth_header, it's sent as the Authorization header too (handy for Grok Bot webhook routines).

Forwarding is protected. Registering a webhook needs the owner's PIN if they set one, and the owner is texted the destination host before forwarding starts; if that text can't be sent, nothing changes. The owner can text UNHOOK to their AI's number anytime to stop it, without going through an agent, or stop it on the dashboard. Removing the key or app sign-in that set up forwarding stops it too. Agents need the current PIN to change or remove the PIN, and webhook changes are limited to five an hour and ten a day.

Verify a webhook (Python)
import hashlib, hmac

def is_valid(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

# body = raw request bytes; signature = request.headers["X-Signature"]

Python SDK

The aitextaroo package (MIT, Python 3.10+) wraps sign-up, sending and the SSE stream with automatic reconnects.

Install
pipx install aitextaroo   # or: pip install aitextaroo
echo_bot.py
import asyncio
from aitextaroo import TextarooClient

async def main():
    client = TextarooClient(api_key="YOUR_KEY")

    # Inbound texts arrive over one outbound SSE connection.
    async for message in client.listen():
        print(message.text, message.has_pin)
        await client.send(f"You said: {message.text}")

asyncio.run(main())

Command line

The same package installs aitextaroo, a command for agents that have a shell but no MCP. Results are JSON and errors go to stderr. Save your key once with aitextaroo-setup --save (or set AITEXTAROO_API_KEY) and every command finds it. PIN commands take the PIN on stdin, not as an argument, and at a terminal they ask for it without echoing, so it stays out of your shell history.

Examples
aitextaroo send "Build finished: 318 tests passing."
aitextaroo ask "Deploy to production? Reply YES or NO" --timeout 120
aitextaroo wait --timeout 60        # wait for the next text
aitextaroo recent                   # texts from the last 5 minutes
aitextaroo relay --to +12125550100 --name Mom "Happy birthday!"   # Pro
aitextaroo verify-pin               # asks for the PIN without echoing; exits 2 if wrong
aitextaroo set-pin                  # choose a 4-8 digit PIN
aitextaroo account
aitextaroo connect codex            # how to add the MCP server to an agent

Bridge CLI

The bridge pipes texts to a CLI agent on your machine and texts back the answer, keeping conversation history in local files. Supported agents: Claude Code, Codex, Hermes, OpenClaw, Grok, Gemini CLI, Antigravity, Goose and Cursor. Any other CLI that takes a prompt and prints a reply, such as NanoClaw, works with --agent-command.

Reference
aitextaroo-bridge [OPTIONS]

  --api-key KEY          API key (default: AITEXTAROO_API_KEY or the saved key)
  --agent NAME           auto, claude, codex, hermes, openclaw, grok, gemini,
                         antigravity, goose, cursor
  --agent-command CMD    Any other CLI agent, e.g. NanoClaw:
                         "pnpm --silent --dir ~/nanoclaw run chat"
  --sessions-dir PATH    Session files (default ~/.aitextaroo/sessions/)
  --no-persist           Keep history in memory only
  --base-url URL         Custom API URL
  -v, --verbose          Debug logging

SMS commands: /help  /new  /status

Limits & errors

  • Free: 10 messages a day. Pro: 200 a day for $5/month. Limits reset at midnight UTC.
  • Texts the agent sends (to the owner or to contacts) count toward the daily limit, and so do contacts' replies forwarded to the owner and the owner's “>” replies to them. The owner's own texts to the agent don't count, but once the limit is reached, texts pause both ways until midnight UTC.
  • Up to 5 texts per minute. Each text is up to 1,600 characters, plain text.
  • Texting contacts (relay) needs Pro. A contact's replies are forwarded to the owner for an hour after the agent (or the owner, with “>”) last texted them, at most 20 an hour and 50 a day from one contact. Once 80% of the day's limit is used, contacts' replies stop being forwarded (the owner is texted once that day), so they can't use up what the owner needs with the agent.
  • Up to 10 API keys per account.
  • Only wrong PINs count: 3 in 5 minutes or 10 in a day pause PIN checks.
  • Errors return {"error": {"code", "message"}}: unauthorized, tier_required, rate_limit_exceeded, daily_limit_reached, pin_required, pin_incorrect, pin_locked, connection_not_found.

Ship SMS in your agent today.

Free plan, no credit card. Four curl commands from zero to your first text.