API Reference
Base URL: https://agenttext-api-production.up.railway.app/v0
Quick Start
Three API calls. That's it.
curl -X POST https://agenttext-api-production.up.railway.app/v0/signup \
-H "Content-Type: application/json" \
-d '{"name": "My Company", "email": "dev@company.com"}'
# → { "api_key": "atx_live_...", "organization": { "plan": "free", "credits": "$5.00" } }curl -X POST https://agenttext-api-production.up.railway.app/v0/inboxes \
-H "Authorization: Bearer atx_live_..." \
-H "Content-Type: application/json" \
-d '{"display_name": "My Agent", "area_code": "415"}'
# → { "inbox_id": "...", "phone_number": "+14155550142", "status": "active" }# Send
curl -X POST https://agenttext-api-production.up.railway.app/v0/inboxes/{inbox_id}/messages \
-H "Authorization: Bearer atx_live_..." \
-H "Content-Type: application/json" \
-d '{"to": "+15551234567", "body": "Verify my account"}'
# Wait for reply (long-poll)
curl -X POST https://agenttext-api-production.up.railway.app/v0/inboxes/{inbox_id}/wait \
-H "Authorization: Bearer atx_live_..." \
-H "Content-Type: application/json" \
-d '{"timeout": 60, "category": "otp"}'
# → { "message": { "body": "Your code is 847291", "otp_code": "847291", "category": "otp" } }Authentication
All API requests (except signup and webhooks) require a Bearer token:
Authorization: Bearer atx_live_xxxxxxxxxxxxYour API key is returned once at signup. It cannot be retrieved again. Store it securely.
Signup
Create an account. No auth required.
| POST | /v0/signup | Create organization and get API key |
# Request
{
"name": "My Company",
"email": "dev@company.com"
}
# Response 201
{
"organization": {
"id": "...",
"name": "My Company",
"email": "dev@company.com",
"plan": "free",
"credits": "$5.00"
},
"api_key": "atx_live_xxxxxxxxxxxx",
"message": "Save this API key — it will not be shown again."
}Inboxes
Each inbox is a real US phone number provisioned on demand.
| POST | /v0/inboxes | Create inbox (provision number) |
| GET | /v0/inboxes | List inboxes |
| GET | /v0/inboxes/:id | Get inbox details |
| PATCH | /v0/inboxes/:id | Update inbox |
| DELETE | /v0/inboxes/:id | Delete inbox (release number) |
Create Inbox
# Request
{
"display_name": "OTP Verifier", // optional
"area_code": "415", // optional, preferred US area code
"labels": ["monitoring"] // optional
}
# Response 201
{
"inbox_id": "...",
"phone_number": "+14155550142",
"display_name": "OTP Verifier",
"status": "active",
"labels": ["monitoring"],
"message_count": 0,
"created_at": "2026-04-13T00:00:00Z",
"updated_at": "2026-04-13T00:00:00Z"
}Cost: $1.15 deducted from free credit per number. Paid plans include numbers in the subscription.
Messages
Send and receive texts. Inbound messages are auto-parsed for OTP codes, categories, and metadata.
| POST | /v0/inboxes/:id/messages | Send a text message |
| GET | /v0/inboxes/:id/messages | List messages (filterable) |
| GET | /v0/inboxes/:id/messages/:msg_id | Get message |
| PATCH | /v0/inboxes/:id/messages/:msg_id | Update labels |
Send Message
# Request
{
"to": "+15551234567", // E.164 format
"body": "Verify my account",
"labels": ["outreach"] // optional
}
# Response 201
{
"message_id": "...",
"inbox_id": "...",
"conversation_id": "...",
"direction": "outbound",
"from_number": "+14155550142",
"to_number": "+15551234567",
"body": "Verify my account",
"status": "queued",
"segments": 1,
"created_at": "2026-04-13T00:00:00Z"
}Inbound Message (auto-parsed)
{
"message_id": "...",
"direction": "inbound",
"body": "Your verification code is 847291. It expires in 10 minutes.",
"status": "received",
"category": "otp",
"otp_code": "847291",
"sender_name": "Stripe",
"links": [],
"opt_out_detected": false,
"labels": ["unread"],
"segments": 1
}List Filters
?direction=inbound | ?category=otp | ?label=unread | ?limit=20
Conversations
Messages are auto-threaded into conversations by contact number.
| GET | /v0/inboxes/:id/conversations | List conversations for inbox |
| GET | /v0/conversations | List all conversations (org-wide) |
| GET | /v0/conversations/:id | Get conversation with messages |
| POST | /v0/conversations/:id/reply | Reply in conversation |
Wait for Message
Long-poll for inbound messages. Perfect for OTP verification flows.
| POST | /v0/inboxes/:id/wait | Wait for inbound message |
# Request
{
"timeout": 60, // max seconds to wait (default 60)
"category": "otp", // optional filter
"since": "2026-04-13T00:00:00Z" // optional, only messages after this time
}
# Response 200 (message arrives)
{
"message": {
"message_id": "...",
"body": "Your code is 847291",
"otp_code": "847291",
"category": "otp",
"created_at": "2026-04-13T00:00:45Z"
}
}
# Response 408 (timeout)
{
"error": "timeout",
"message": "No matching message received within 60 seconds"
}Billing
Upgrade from free to a paid plan via Stripe Checkout.
| POST | /v0/billing/checkout | Create Stripe Checkout session |
| POST | /v0/billing/portal | Open Stripe Customer Portal |
# Request
{
"plan": "builder" // "builder" ($29/mo) or "scale" ($149/mo)
}
# Response 200
{
"checkout_url": "https://checkout.stripe.com/..."
}MCP Server
Use AgentText directly from Claude, Cursor, or any MCP-compatible agent.
npx agenttext-mcpClaude Desktop / Cursor Config
{
"mcpServers": {
"agenttext": {
"command": "npx",
"args": ["-y", "agenttext-mcp"],
"env": {
"AGENTTEXT_API_KEY": "atx_live_..."
}
}
}
}Available Tools
| create_inbox | Provision a new phone number |
| list_inboxes | List all your inboxes |
| send_message | Send a text from an inbox |
| list_messages | List messages with filters |
| wait_for_message | Wait for an inbound text (OTP, etc.) |
Error Codes
| Status | Code | Meaning |
|---|---|---|
| 401 | auth_error | Invalid or missing API key |
| 402 | payment_required | Credits exhausted, upgrade needed |
| 403 | forbidden | Plan limit reached |
| 404 | not_found | Resource not found |
| 422 | validation_error | Invalid request body |
| 429 | rate_limited | Too many requests |