# Developer docs: SMS API, MCP server, Agent Skill and SDK

> AI Text-a-roo is an SMS gateway for AI agents: remote MCP server, REST API, Python SDK and a local bridge, all over outbound HTTPS.

Canonical: https://aitextaroo.com/docs · Updated: 2026-10-25

## Quickstart

```bash
# 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

https://api.aitextaroo.com/mcp (streamable HTTP). Tools: `send_text`, `wait_for_reply`, `get_recent_messages`, `text_contact`, `verify_pin`, `set_pin`, `get_account`, `get_upgrade_link`, `set_webhook`, `remove_webhook`, `list_connections`, `remove_connection`, `get_help`. Full reference: https://aitextaroo.com/docs/mcp.md

## Agent Skill

SKILL.md: https://aitextaroo.com/skills/aitextaroo/SKILL.md · ZIP: https://aitextaroo.com/skills/aitextaroo.zip

- **Claude and Claude Duet:** Download the ZIP, then upload it under Customize → Skills.

  ```
  https://aitextaroo.com/skills/aitextaroo.zip
  ```
- **Claude Code:** Install the plugin, which bundles the skill and the MCP server (in a session):

  ```
  /plugin marketplace add rwfresh/aitextaroo-clients
  /plugin install aitextaroo@aitextaroo
  ```
- **Codex:** Install the plugin, which bundles the skill and the MCP server:

  ```
  codex plugin marketplace add rwfresh/aitextaroo-clients
  codex plugin add aitextaroo@aitextaroo
  ```
- **Gemini CLI:** Install the extension:

  ```
  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):

  ```
  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:

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

## REST API

Base URL https://api.aitextaroo.com/v1. OpenAPI: https://api.aitextaroo.com/openapi.json

| Method | Path | API key | What it does |
| --- | --- | --- | --- |
| POST | `/v1/auth/verify` | no | Text a 6-digit code to a phone: {"phone": "+1…"} |
| POST | `/v1/auth/confirm` | no | Confirm 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/send` | yes | Text the owner {"text"}, or a contact on Pro {"text", "to", "recipient_name"} |
| POST | `/v1/messages/wait` | yes | Wait up to 120 s for the owner's next text: {"timeout_seconds": 60} |
| GET | `/v1/messages/recent` | yes | Texts from the last five minutes (?after_id= cursor) |
| GET | `/v1/stream` | yes | Server-Sent Events stream of inbound texts (Last-Event-ID replay) |
| POST | `/v1/webhook` | yes | Forward inbound texts to a URL: {"url", "auth_header", "pin"}. The PIN is required if one is set; the owner is texted first |
| DELETE | `/v1/webhook` | yes | Stop webhook delivery (the owner is texted) |
| GET | `/v1/account` | yes | Plan, AI number, PIN status, usage and daily limit |
| POST | `/v1/verify-pin` | yes | Check a PIN the owner texted: {"pin"} |
| POST | `/v1/account/pin` | yes | Set the owner's PIN {"pin"}, or change it {"pin", "current_pin"}. The owner is texted first |
| DELETE | `/v1/account/pin` | yes | Remove the PIN: {"current_pin"}. The owner is texted first |
| GET | `/v1/account/connections` | yes | Keys 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}` | yes | Disconnect a key or app sign-in: {"pin"} if one is set. The owner is texted; forwarding it set up stops too |
| POST | `/v1/billing/checkout` | yes | Stripe checkout link for Pro |
| POST | `/v1/billing/portal` | yes | Stripe 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 goes to exactly one place: a waiting wait_for_reply call or POST /v1/messages/wait; otherwise the live /v1/stream connection and your webhook; otherwise it waits in memory for up to five minutes. So an agent that only runs while you chat with it won't see texts sent at other times unless a webhook is registered; cloud agents (for example a Grok Bot webhook routine) can register one with the set_webhook MCP tool. Webhooks are signed with an X-Signature header (hex HMAC-SHA256 of the raw body).

Forwarding is protected: registering a webhook needs the owner's PIN if one is set, the owner is texted the destination host before forwarding starts (if that text can't be sent, nothing changes), and the owner can text UNHOOK to their AI's number anytime to stop it, 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, so an agent can't remove it to get around this, and webhook changes are limited to five an hour and ten a day.

```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

```bash
pipx install aitextaroo   # or: pip install aitextaroo
```

```python
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 package also installs `aitextaroo`, for agents with a shell but no MCP. JSON output; the key comes from `aitextaroo-setup --save` or AITEXTAROO_API_KEY. PIN commands read the PIN from stdin, or from a hidden prompt at a terminal.

```bash
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

```
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. 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, 1,600 characters each.
- 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.
- PIN checks: only wrong PINs count; 3 in 5 minutes or 10 in a day pause them.
- Error codes: unauthorized, tier_required, rate_limit_exceeded, daily_limit_reached, pin_required, pin_incorrect, pin_locked, connection_not_found.
