AgentCell

AgentCell — Agent Onboarding Guide

End-to-end playbook for an AI agent (or agent-assisted developer) to go from zero to sending and receiving SMS (MMS later) — without human console access except OTP. Payment supports fully autonomous x402 and MPP; Stripe Checkout remains available when a human pays by card. When the human does need the UI, the agent can issue a console login link or they can sign in at /login on agentcell.store (redirects to /user) with their sign-up phone number.
Platform details: AGENTCELL_PLATFORM_SPEC.md | Product concept: AGENTCELL_CONCEPT.md


Table of Contents

  1. Overview
  2. Prerequisites
  3. Onboarding Phases
  4. Receive Path Options
  5. Payment Flow
  6. Human Console Login
  7. Compliance & First Message Rules (User Responsibility)
  8. Error Handling Reference
  9. Copy Blocks (Full Flow)
  10. Production Checklist

1. Overview

This guide walks an AI agent through 9 platform phases plus user-owned compliance (10DLC/A2P is not handled by AgentCell). The recommended path for Cursor/Claude is MCP (agentcell-mcp); CI and scripts use CLI; custom integrations use REST.

Principal–agent assumption: The AI agent uses the API on behalf of the account owner (human on file). The owner is responsible for telecom compliance; AgentCell provides hosting and messaging only.

sequenceDiagram
    participant Agent as AI Agent
    participant MCP as agentcell-mcp
    participant API as AgentCell API
    participant Human as Human
    participant Stripe as Stripe
    participant Carrier as Carrier

    Agent->>MCP: agent_sign_up
    MCP->>API: POST /agent/sign-up
    API->>Human: OTP via SMS + email
    Human->>Agent: OTP code
    Agent->>MCP: agent_verify
    MCP->>API: POST /agent/verify

    Agent->>MCP: pay (checkout | x402 | mpp)
    alt Stripe Checkout
        MCP->>API: POST /billing/checkout
        API->>Stripe: Checkout session
        Stripe->>Human: Payment UI
        Human->>Stripe: Pay setup + first month
        Stripe->>API: billing.payment_succeeded
    else x402 or MPP
        MCP->>API: POST /cells or /billing/mpp/pay
        API-->>Agent: 402 Payment Required
        Agent->>API: Retry with PAYMENT-SIGNATURE or MPP Credential
        API->>API: billing.x402.settled or billing.mpp.settled
    end

    Agent->>MCP: create_cell
    MCP->>API: POST /cells
    API->>Carrier: Provision device + number

    Note over Agent,Human: User registers 10DLC/A2P externally (not AgentCell)

    Agent->>MCP: set_webhook
    Agent->>MCP: send_message

    Carrier->>API: Inbound SMS
    API->>Agent: webhook cell.message.received
    Agent->>MCP: reply_message

Phase summary

| # | Phase | Human required? | |---|-------|-----------------| | 1 | Discover | No | | 2 | Sign up | No (agent calls API) | | 3 | Verify | Yes (OTP from human) | | 4 | Pay | Yes (Stripe Checkout) | | 5 | Provision cell | No | | 6 | User compliance (10DLC/A2P, external) | Yes (owner registers with carrier/TCR) | | 7 | Configure events | No | | 8 | First send | No | | 9 | First receive & reply | No | | 10 | Operate | No |


2. Prerequisites

Before starting, the agent should:

  • [ ] Load documentation index: https://agentcell.store/docs/llms.txt
  • [ ] Have MCP configured (hosted URL or npx -y @agentcell/mcp) or CLI (npm i -g @agentcell/cli) or SDK (@agentcell/sdk / agentcell PyPI) + API access
  • [ ] Know the human's phone (E.164) and email for sign-up OTP
  • [ ] Have a webhook URL (HTTPS) ready, or plan to use WebSockets (no public URL)
  • [ ] Understand pricing: org $29 + cell setup $150 + cell $50 = $229 / $79. SMS included.
  • [ ] For US outbound SMS: owner must register 10DLC/A2P externally — AgentCell does not file registrations (§10 concept)

Reference platforms:

Install CLI or MCP (npm downloads Go binary):

npm i -g @agentcell/cli         # exposes `agentcell` command
npx -y @agentcell/mcp           # optional local stdio MCP

Or build from source (Go 1.23+):

go build -o agentcell ./cmd/cli
go build -o agentcell-mcp ./cmd/mcp

3. Onboarding Phases

Phase 1: Discover

Goal: Orient to account state and documentation.

MCP:

account_overview   # after auth only; skip pre-sign-up

Pre-sign-up: Fetch https://agentcell.store/docs/llms.txt and read agent-onboarding.md.

CLI:

# No auth yet — read docs
curl -s https://agentcell.store/docs/llms.txt | head -50

Phase 2: Sign up

Goal: Obtain api_key and organization_id.

MCP tool: agent_sign_up

| Parameter | Required | Example | |-----------|----------|---------| | human_phone | Yes | +15551234567 | | human_email | Yes | [email protected] | | username | Yes | my-agent |

REST:

curl -X POST https://api.agentcell.store/v1/agent/sign-up \
  -H "Content-Type: application/json" \
  -d '{
    "human_phone": "+15551234567",
    "human_email": "[email protected]",
    "username": "my-agent"
  }'

Response:

{
  "api_key": "ac_xxxxxxxx",
  "organization_id": "org_xxxxxxxx",
  "otp_sent_to": ["+15551234567", "[email protected]"]
}

CLI:

agentcell agent sign-up \
  --human-phone +15551234567 \
  --human-email [email protected] \
  --username my-agent

Store securely: api_key, organization_id. Set AGENTCELL_API_KEY=ac_....

Notes:

  • Idempotent: same email/phone rotates key and resends OTP if expired
  • Blocklisted domains (e.g. example.com) rejected — use real email
  • Pattern from AgentMail sign-up

Failures:

| Error | Fix | |-------|-----| | 400 validation | Check E.164 phone format | | 409 already exists | Call sign-up again to rotate key |


Phase 3: Verify

Goal: Unlock outbound messaging to external numbers.

Human action: Read 6-digit OTP from SMS and email; provide to agent.

MCP tool: agent_verify with otp_code

REST:

curl -X POST https://api.agentcell.store/v1/agent/verify \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"otp_code": "123456"}'

CLI:

export AGENTCELL_API_KEY=ac_...
agentcell agent verify --otp-code 123456

Until verified:

  • Inbound SMS to assigned numbers works after cell creation
  • Outbound to only the signup phone/email allowed
  • Other sends return 403 NOT_VERIFIED

Phase 3b: Human console access (optional)

Goal: Let the human owner open /user on agentcell.store to view account status, pay bills, and copy API keys / MCP config — not to manage cells, webhooks, or messaging (agent handles that via API/MCP/CLI).

When: Anytime after Phase 3 verify. Often used before Phase 4 (Stripe checkout) or when the agent needs the human to review billing.

Option A — Agent sends magic login link (recommended)

MCP tool: create_console_login_link

curl -X POST https://api.agentcell.store/v1/auth/login-links \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_path": "/user/billing",
    "delivery": "sms",
    "label": "Complete setup payment"
  }'

Response: login_url — human opens once → automatic login (15 min default TTL).

Deliver to human via:

  • delivery: "sms" — sent to org human_phone
  • delivery: "email" — sent to org human_email
  • delivery: "none" — agent pastes URL in chat
agentcell console login-link create --redirect-path /user/billing --delivery sms

Option B — Human logs in with sign-up phone

Human visits https://console.agentcell.store/login:

  1. Enter human_phone (same E.164 used at sign-up)
  2. Receive SMS OTP
  3. Enter code → console session

No API key required for this path.

Not admin: This is the customer console. Platform operators use console.agentcell.store/admin with a phone enrolled in the admins table — see AGENTCELL_ADMIN.md.


Phase 4: Pay

Goal: Payment method or prepaid balance on file; account funded for setup + first month.

Ongoing monthly hosting and service fees keep your cell active. If payment fails, service suspends; reinstatement costs $150 USD within 30 days, or ownership is forfeited. See AGENTCELL_OWNERSHIP.md.

Choose one payment path:

Path A — Stripe Checkout (human card)

MCP tool: create_setup_checkout

| Parameter | Description | |-----------|-------------| | tier | starter, pro, or enterprise | | success_url | Redirect after payment | | cancel_url | Redirect on cancel |

curl -X POST https://api.agentcell.store/v1/billing/checkout \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tier": "pro",
    "success_url": "https://my-app.com/billing/success",
    "cancel_url": "https://my-app.com/billing/cancel"
  }'

Human action: Open checkout_url in browser; pay setup fee + first month.

Path B — x402 (agent wallet, no browser)

MCP tools: get_payment_options, pay_with_x402

  1. Agent calls GET /billing/x402/requirements?intent=setup&tier=pro (or POST /cells and handle 402).
  2. API returns 402 + PAYMENT-REQUIRED header (USDC amount, network, destination).
  3. Agent signs with wallet; retries with PAYMENT-SIGNATURE header.
  4. On settle → subscription active + prepaid credited if applicable; webhook billing.x402.settled.
# SDK handles 402 loop automatically:
agentcell billing pay x402 --intent setup --tier pro

Requirements: Agent wallet with USDC on supported network (Base, Solana). Optional: POST /billing/x402/wallets to register org wallet.

Path C — MPP (Machine Payments Protocol)

MCP tools: get_payment_options, pay_with_mpp

  1. Discovery: GET https://api.agentcell.store/.well-known/mpp
  2. POST /billing/mpp/pay with intent=setup, tier=pro402 Challenge.
  3. Agent authorizes via Stripe SPT (method=stripe) or Tempo stablecoin (method=tempo).
  4. Retry with MPP Credential → Receipt + webhook billing.mpp.settled.
agentcell billing pay mpp --intent setup --tier pro --method tempo
# or MCP: pay_with_mpp(intent="setup", tier="pro", method="stripe")

After any path: Poll billing status:

agentcell billing status
# or MCP: get_billing_status / get_payment_options

Failures:

| Error | Fix | |-------|-----| | 402 PAYMENT_REQUIRED | Complete checkout, x402, or MPP before create_cell | | X402_SETTLEMENT_FAILED | Retry with fresh signature; check wallet balance | | MPP_CHALLENGE_EXPIRED | Re-request challenge via POST /billing/mpp/pay | | MPP_INVALID_CREDENTIAL | Regenerate SPT or Tempo proof | | Checkout expired | Create new checkout session (Stripe path only) |

Pricing charged:

  • $229 + tax due at setup (org $29 + cell setup $150 + first cell month $50)
  • $79 / month after
  • SMS is included in the cell plan (no per-message fee)

See pricing and AGENTCELL_CONCEPT.md §6.


Phase 5: Provision cell

Goal: A waiting cell, then a numbered radio after the handset claims.

create_cell after payment creates pending_provision plus a phone_orders snapshot ($229 / $79). It does not return an E.164. Typically 1–72 hours.

An operator enters tracking or a target E.164 and sends AGENTCELL-SETUP v1 / c:<claim> from the connected admin handset. The default-SMS app (sideload / operator image — not Play Store) claims; the API issues pk_live_ (never in SMS) and the phone stays on WSS /v1/device/ws. GET cell then includes public phone (no ADB) and public order.

MCP tool: create_cell (no client_id; MCP has no setup-SMS / claim tools)

| Parameter | Description | |-----------|-------------| | display_name | Friendly name (required) | | area_code | Preferred US area code (best-effort, optional) | | country | Default US |

REST:

curl -X POST https://api.agentcell.store/v1/cells \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "My Agent Cell",
    "area_code": "415"
  }'

Create response: cell_id, empty phone_number, status: pending_provision. GET later may include order and phone.

Wait until numbered:

agentcell cells get --cell-id cell_abc123
agentcell cells health --cell-id cell_abc123
# health is online when phones.ws_connected

CLI:

agentcell cells create --display-name "My Agent Cell" --area-code 415

Notes:

  • Do not pass client_id on cell create (CLI has no --client-id on this command).
  • Additional phones: Call create_cell again — each cell is another $150 + $50/mo on top of org $29.
  • Send before an E.164 → 409 CELL_NOT_READY. Send with no connected radio → 503 CARRIER_UNAVAILABLE.
  • Outbound US SMS still requires your external 10DLC/A2P registration (Phase 6).

Failures:

| Error | Fix | |-------|-----| | 402 | Complete payment (Phase 4) | | 409 CELL_NOT_READY | Wait for claim / E.164 | | 503 CARRIER_UNAVAILABLE | Handset must stay on the device WebSocket |


Phase 6: User compliance (10DLC/A2P — external)

Goal: Enable outbound SMS to US mobile numbers per carrier rules.

Not handled by AgentCell. You (the account owner) must register 10DLC/A2P with your carrier, The Campaign Registry (TCR), or your compliance vendor and associate registration with each number/cell you use for outbound A2P SMS.

AgentCell assumption: The AI agent sends messages on behalf of the owner, who accepts legal and regulatory liability.

| Step | Who | Action | |------|-----|--------| | 1 | Owner | Register brand and campaign externally | | 2 | Owner | Link campaign to AgentCell-provisioned number(s) per carrier process | | 3 | Agent | Record external IDs via PATCH /pods/{pod_id}/compliance or cell metadata | | 4 | Agent | Test outbound; handle carrier rejections in your error logic |

Inbound: Works when the number is active — no AgentCell registration step (same as AgentPhone inbound pattern).

While unregistered externally: Outbound to US mobiles may fail at the carrier; API may return success but message never delivers. See carrier limits.

Reference: AgentPhone 10DLC guide for background on carrier requirements — AgentPhone registers in-product; AgentCell does not. Use that doc to understand rules, then complete registration through your chosen provider.

No AgentCell API for registration — there is no POST /registration/a2p, no submit_a2p_registration MCP tool, and no console wizard.


Phase 7: Configure events

Goal: Receive inbound messages in real time.

Option A: Webhooks (recommended for servers)

MCP tool: set_webhook

curl -X POST https://api.agentcell.store/v1/webhooks \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhook",
    "event_types": ["cell.message.received", "cell.message.delivered"],
    "context_limit": 10
  }'

Save secret from response for signature verification.

Handler requirements:

  1. Return 200 OK immediately
  2. Process payload asynchronously
  3. Verify HMAC: {timestamp}.{raw_body} with secret
  4. Reject timestamps > 5 minutes old
  5. Dedupe with X-Webhook-ID / event_id

Per-cell webhook: Use set_cell_webhook to scope to one cell.

Option B: WebSockets (no public URL)

Connect to wss://api.agentcell.store/v1/events/stream with Bearer token.

Subscribe to cell.message.received. Pattern from AgentMail WebSockets.

Option C: Polling (fallback)

agentcell cells messages list --cell-id cell_abc123 --labels unread

Mark processed messages with --add-labels read --remove-labels unread.

Test webhook:

agentcell webhooks test

Phase 8: First send

Goal: Send first outbound SMS/MMS.

First-message compliance (US): Include brand name, opt-in acknowledgment, and STOP instructions:

Hi! This is Acme Corp. You're receiving this because you signed up
for updates. Reply STOP at any time to unsubscribe.

MCP tool: send_message

curl -X POST https://api.agentcell.store/v1/cells/cell_abc123/messages/send \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: first-message-v1" \
  -d '{
    "to": "+15559876543",
    "body": "Hi! This is Acme Corp. You opted in for updates. Reply STOP to unsubscribe."
  }'

MMS:

{
  "to": "+15559876543",
  "body": "Here is your photo.",
  "media_urls": ["https://example.com/photo.jpg"]
}

CLI:

agentcell cells messages send \
  --cell-id cell_abc123 \
  --to +15559876543 \
  --body "Hi! This is Acme Corp. Reply STOP to unsubscribe."

Failures:

| Code | Meaning | Action | |------|---------|--------| | 403 NOT_VERIFIED | Phase 3 incomplete | Verify OTP | | 402 | Insufficient balance | Top up / check subscription | | 422 CARRIER_REJECTED | Outbound blocked by carrier (often missing external 10DLC) | Complete Phase 6 with your carrier/TCR | | 429 OUTBOUND_LIMIT_REACHED | Daily cap | Wait for reset or scale cells |


Phase 9: First receive & reply

Goal: Handle inbound message and reply in thread.

Inbound webhook payload:

{
  "event_type": "cell.message.received",
  "event_id": "evt_abc123",
  "cell": {
    "cell_id": "cell_abc123",
    "phone_number": "+14155551234"
  },
  "message": {
    "message_id": "msg_xyz789",
    "conversation_id": "conv_def456",
    "from": "+15559876543",
    "to": "+14155551234",
    "body": "When will my order arrive?",
    "extracted_body": "When will my order arrive?",
    "channel": "sms",
    "labels": ["received", "unread"]
  },
  "conversation_state": null,
  "recent_history": []
}

Handler steps:

  1. Verify signature
  2. Check idempotency (event_id not seen before)
  3. Process message.body or extracted_body
  4. Mark read: PATCH .../messages/{id} with add_labels: ["read"], remove_labels: ["unread"]
  5. Reply:

MCP: reply_message

curl -X POST https://api.agentcell.store/v1/cells/cell_abc123/messages/msg_xyz789/reply \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body": "Your order arrives Thursday. Tracking: 1Z999..."}'

Update conversation state (optional, for multi-turn context):

curl -X PATCH https://api.agentcell.store/v1/conversations/conv_def456 \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metadata": {"order_id": "ORD-4521", "customer_name": "Jane"}}'

Full thread by number pair (line ↔ contact, with stats):

curl "https://api.agentcell.store/v1/conversations/between?from=%2B14155551234&to=%2B15559876543" \
  -H "Authorization: Bearer $AGENTCELL_API_KEY"

# Stats only — outbound/inbound counts, segments, characters
curl "https://api.agentcell.store/v1/conversations/between?cell_id=cell_support&contact=%2B15559876543&include_messages=false" \
  -H "Authorization: Bearer $AGENTCELL_API_KEY"

MCP: get_conversation_between | CLI: agentcell conversations between --from ... --to ...

Future webhooks include conversation_state automatically (AgentPhone pattern).


Phase 10: Operate

Goal: Production-ready agent operation.

Recommended setup:

| Feature | Purpose | |---------|---------| | Messaging settings | include_stop_footer, auto_ignore_on_stop, ignore_list_enabled on cell or pod | | TCPA quiet hours | Pod-only tcpa_quiet_hours — gates pod-scoped sends; direct cell send without pod_id bypasses | | Ignore lists | Suppress inbound webhooks and block outbound to opted-out numbers (cell and/or pod scope) | | Pod cycle send | Blast a recipient list across pod phones, 1 msg/sec/cell, single_message or per_recipient | | Lists | Block spam numbers; allow-only VIP senders | | Drafts | Human-in-the-loop before sensitive sends | | Pods | Multi-tenant SaaS (one pod per customer) | | Labels | Campaign tracking, triage, read/unread | | Usage monitoring | get_usage daily; watch segment counts vs your registered campaign tier |

Enable STOP footer + auto-ignore on a pod:

curl -X PATCH https://api.agentcell.store/v1/pods/pod_acme \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_settings": {
      "include_stop_footer": true,
      "auto_ignore_on_stop": true,
      "ignore_list_enabled": true,
      "tcpa_quiet_hours": {
        "enabled": true,
        "window_start": "08:00",
        "window_end": "21:00",
        "timezone_mode": "recipient_local",
        "queue_until_open": true
      }
    }
  }'

Direct reply bypasses pod quiet hours (omit pod_id):

curl -X POST https://api.agentcell.store/v1/cells/cell_abc123/messages/send \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -d '{"to": "+15559876543", "body": "Your ticket was updated."}'

Pod cycle send (single message, many recipients):

curl -X POST https://api.agentcell.store/v1/pods/pod_acme/messages/cycle \
  -H "Authorization: Bearer $AGENTCELL_API_KEY" \
  -d '{
    "client_id": "promo-v1",
    "mode": "single_message",
    "body": "Flash sale ends tonight!",
    "recipients": ["+15551111111", "+15552222222", "+15553333333"]
  }'

MCP: get_pod_overview, list_pod_messages, get_conversation_between, get_pod_conversation_between, get_pod_compliance, list_pod_stop_list, update_pod_settings, pod_cycle_send, check_quiet_hours

MCP maintenance prompts:

  • "Show usage for the last 7 days."
  • "List unread messages on my support cell."
  • "Show all outbound messages from pod acme today."
  • "Get the full conversation between our support line and +15559876543."
  • "How many SMS segments have we sent to +15559876543?"
  • "What's on the stop list for pod acme?"
  • "Get 10DLC compliance info for pod acme."
  • "Add +15551112222 to the receive block list."
  • "Rotate a promo message through my sales pod to these 20 numbers."
  • "Enable STOP footer and auto-ignore on pod acme."
  • "Is it TCPA-safe to text +15559876543 from pod acme right now?"

CLI:

agentcell usage daily --days 7
agentcell cells messages list --cell-id cell_abc123 --labels unread

4. Receive Path Options

| Method | Best for | Public URL? | AgentMail | AgentPhone | |--------|----------|-------------|-----------|------------| | Webhooks | Server deployments | Yes (HTTPS) | Yes | Yes | | WebSockets | Local/dev agents | No | Yes | — | | Polling | Debugging only | No | Fallback | Fallback |

Webhook verification (Node.js)

const crypto = require("crypto");

function verifyWebhook(rawBody, signature, timestamp, secret) {
  if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) return false;
  const signed = timestamp + "." + rawBody;
  const expected = crypto.createHmac("sha256", secret).update(signed).digest("hex");
  return signature === `sha256=${expected}`;
}

Return 200 immediately; process async. Dedupe on event_id.


5. Payment Flow

AgentCell billing differs from AgentMail (plan tiers) and AgentPhone (pay-as-you-go credits). Three rails: Stripe, x402, MPP.

flowchart TD
    SignUp[Agent sign-up] --> Verify[OTP verify]
    Verify --> PayChoice{Payment rail}
    PayChoice --> Checkout[Stripe Checkout]
    PayChoice --> X402[x402 PAYMENT-SIGNATURE]
    PayChoice --> MPP[MPP Challenge/Credential]
    Checkout --> Funded[Account funded]
    X402 --> Funded
    MPP --> Funded
    Funded --> CreateCell[create_cell]
    CreateCell --> SetupFee[Setup fee applied if not in checkout]
    CreateCell --> Monthly[Monthly hosting + service subscription]
    Monthly --> Usage[Daily usage meter: volume only, SMS included]
    Usage --> Invoice[Monthly invoice: org + cell fees]

| Charge | When | Amount | |--------|------|--------| | Setup fee | Checkout, x402, MPP, or first create_cell 402 | $229 (org + setup + first month) | | Hosting + org | Monthly subscription or prepaid renewal | $79/mo | | SMS | Included | $0 |

x402 details

| Item | Value | |------|-------| | Protocol | x402 v2 — HTTP 402 + PAYMENT-REQUIRED / PAYMENT-SIGNATURE / PAYMENT-RESPONSE | | Default asset | USDC (Base, Solana) | | Schemes | exact, upto, optional batch-settlement | | Facilitator | AgentCell-hosted /billing/x402/facilitator/verify + /settle | | MCP | pay_with_x402, get_payment_options |

MPP details

| Item | Value | |------|-------| | Protocol | Machine Payments Protocol — co-authored Stripe + Tempo | | Discovery | GET https://api.agentcell.store/.well-known/mpp | | Methods | stripe (SPT / Link), tempo (stablecoin, min ~$0.01) | | Server | mppx integration; Stripe PaymentIntent with machine_payment: true | | MCP | pay_with_mpp, get_payment_options |

Prepaid & hybrid billing

Agents can maintain a prepaid balance (x402/MPP deposits) instead of card-on-file:

agentcell billing prepaid deposit --amount-usd 200 --rail mpp
agentcell billing prepaid balance

Configure auto top-up: PATCH /billing/preferences or MCP set_billing_preferences.

Grace period: 30 days on failed renewal before number release (Stripe dunning or prepaid depletion).

Check status anytime:

agentcell billing status
agentcell billing payment-options
curl https://api.agentcell.store/v1/billing/status -H "Authorization: Bearer $AGENTCELL_API_KEY"

6. Human Console Login

The human owner uses https://console.agentcell.store/user to observe, pay, and connect the agent — not to operate the platform.

| Method | Initiator | Summary | |--------|-----------|---------| | Magic login link | Agent | create_console_login_link → human opens URL → read-only dashboard + billing pay + API keys | | Phone OTP | Human | /login → sign-up human_phone → SMS code |

| In console | Via agent (API/MCP/CLI) | |------------|-------------------------| | View cells, messages, usage, agent status & activity, webhook delivery log | Create cells, send SMS, configure webhooks | | Pay invoices, reinstatement (Stripe) | x402/MPP machine payments | | Create/copy API keys, MCP/CLI setup snippets | Scoped keys, permissions, all management |

See Phase 3b. Full spec: AGENTCELL_PLATFORM_SPEC.md §4.2b, §9.3. Page-level UI breakdown: AGENTCELL_FRONTEND_CONSOLE.md.

Agent observability (/user/agent)

Read-only panels for the human owner:

| Panel | Shows | |-------|--------| | Status | active / idle / offline / never_connected; time since last API/MCP/WebSocket activity | | Last connection | Client type (MCP stdio/hosted, CLI, SDK, REST, WebSocket), API key name, last_seen_at | | Live sessions | Whether MCP and/or WebSocket streams are connected now | | 24h stats | API requests, logged actions, messages sent, errors | | Activity feed | Recent agent actions with summaries (messages.send, cells.create, webhooks.set, …) | | Connections | Per API key: client version, first/last seen, request count |

Typical agent prompt: "Check /user/agent — you'll see I'm active and what I've sent in the last hour."

Security:

  • Magic links: single-use, 15 min default TTL, revocable via revoke_console_login_link
  • Phone login: verified org human_phone only
  • Console cannot send SMS or change webhooks/pods/cells

7. Compliance & First Message Rules (User Responsibility)

AgentCell does not register 10DLC/A2P. The account owner completes compliance externally (Phase 6). The agent operates on the owner's behalf.

10DLC (US outbound)

  • Required by US carriers for A2P SMS from 10-digit numbers
  • You register with carrier/TCR/compliance vendor — not via AgentCell API
  • Daily segment limits depend on your external campaign tier — see AGENTPHONE_BREAKDOWN.md §5

First outbound to new contact

Must include:

  1. Brand name
  2. Opt-in confirmation
  3. Opt-out (Reply STOP)

Non-compliant messages may show as sent but never deliver.

MMS rules

  • Media URLs: public HTTPS
  • Max 5 MB for carrier MMS
  • Types: JPEG, PNG, GIF, MP3, M4A, MP4, PDF, vCard, etc.

STOP handling & ignore lists

When messaging settings are enabled:

| Setting | Behavior | |---------|----------| | include_stop_footer | Outbound SMS append STOP instructions | | auto_ignore_on_stop | STOP keyword adds sender to pod/cell ignore list | | ignore_list_enabled | Ignored numbers: no inbound webhook; outbound returns IGNORED_RECIPIENT |

Pod-level ignore applies to all cells in the pod when the pod has ignore_list_enabled: true. Cell-level ignore adds entries for that line only. Effective ignored set = union of both when each scope is enabled.

If settings are off, you handle STOP and opt-out manually (Lists API or your store).

TCPA quiet hours (pod)

Configure on the pod only. When tcpa_quiet_hours.enabled is true:

  • Pod cycle send and any send with pod_id in the request are blocked or deferred outside 8 AM–9 PM recipient local time (configurable).
  • POST /cells/{id}/messages/send without pod_id bypasses quiet hours — use for replies and transactional one-offs you authorize.
  • Pods without the setting, and org-level cells not in a pod, are unrestricted by this feature.

Preflight: GET /pods/{pod_id}/quiet-hours/check?to=+1... or MCP check_quiet_hours.


8. Error Handling Reference

| HTTP | Code | Retriable? | Phase | Fix | |------|------|------------|-------|-----| | 402 | PAYMENT_REQUIRED | No | 4, 5 | Stripe checkout, pay_with_x402, or pay_with_mpp | | 402 | X402_SETTLEMENT_FAILED | Maybe | 5 | Retry x402 with fresh signature | | 402 | MPP_SETTLEMENT_FAILED | Maybe | 5 | New MPP challenge | | 403 | NOT_VERIFIED | No | 3 | Verify OTP | | 403 | FORBIDDEN | No | — | Check API key permissions | | 409 | IDEMPOTENCY_CONFLICT | No | 5, 8 | Same key, different body | | 422 | TCPA_QUIET_HOURS | No | 10 | Wait for window, enable queue_until_open, or direct cell send without pod_id | | 422 | IGNORED_RECIPIENT | No | 10 | Remove from recipients or delete ignore entry | | 422 | CARRIER_REJECTED | No | 6 | Complete external 10DLC/A2P for this number | | 422 | CELL_NOT_READY | Yes | 5 | Poll health until online | | 401 | CONSOLE_LINK_INVALID | No | 3b, 6 | Request new login link from agent | | 429 | CONSOLE_CHALLENGE_RATE_LIMITED | Yes | 6 | Wait before retrying phone OTP | | 429 | CONVERSATION_STREAK_LIMIT | No | 8 | Wait for contact reply | | 429 | OUTBOUND_LIMIT_REACHED | No | 8 | Daily reset; add cells | | 502 | CARRIER_ERROR | Maybe | 8 | Confirm delivery before retry |

Idempotency:

  • Creates: reuse same client_id on pods, drafts, and cycle jobs — not on cell create
  • Sends: reuse same Idempotency-Key within 24h

No idempotency on AgentPhone sends — AgentCell adds Idempotency-Key (AgentMail pattern). Always confirm failed sends didn't deliver before retry.


9. Copy Blocks (Full Flow)

Python

"""
AgentCell full onboarding — copy into Cursor/Claude.

Phases: sign-up → verify → checkout → create cell → webhook → send → reply.
Requires: pip install agentcell; human provides OTP; payment via Stripe OR x402 OR MPP wallet.
"""
import os
import time
from agentcell import AgentCell

# Phase 2: Sign up (no API key)
client = AgentCell()
resp = client.agent.sign_up(
    human_phone="+15551234567",
    human_email="[email protected]",
    username="my-agent",
)
api_key = resp.api_key
print("OTP sent to:", resp.otp_sent_to)

# Phase 3: Verify (human provides OTP)
client = AgentCell(api_key=api_key)
client.agent.verify(otp_code="123456")  # replace with real OTP

# Optional: send human a console login link (billing UI, fleet view)
# link = client.auth.create_console_login_link(redirect_path="/user/billing", delivery="sms")
# print("Console login sent:", link.login_url)

# Phase 4: Payment — choose one path

# Path A: Stripe (human opens checkout_url)
checkout = client.billing.create_checkout(
    tier="pro",
    success_url="https://example.com/success",
    cancel_url="https://example.com/cancel",
)
print("Pay at:", checkout.checkout_url)
input("Press Enter after payment completes...")

# Path B: x402 (autonomous — requires wallet env)
# client = AgentCell(api_key=api_key, payment_mode="x402", wallet_key=os.environ["WALLET_KEY"])
# client.billing.pay_with_x402(intent="setup", tier="pro")

# Path C: MPP (autonomous — SPT or Tempo)
# client.billing.pay_with_mpp(intent="setup", tier="pro", method="tempo")

# Phase 5: Create cell (no number yet; no client_id)
cell = client.cells.create(
    display_name="My Agent Cell",
    area_code="415",
)
print("Cell:", cell.cell_id, cell.phone_number)  # phone_number empty until claim

while True:
    got = client.cells.get(cell.cell_id)
    if got.get("phone_number"):
        break
    time.sleep(30)

# Phase 6: User compliance (external — not AgentCell API)
# Owner registers 10DLC/A2P with carrier/TCR; record metadata on the pod:
client.pods.update_compliance(
    "pod_acme",
    a2p_10dlc={
        "brand_id": "BXXXXXX",
        "campaign_id": "CXXXXXX",
        "status": "approved",
        "status_source": "user_declared",
    },
)

# Phase 7: Webhook
wh = client.webhooks.create(
    url="https://your-server.com/webhook",
    event_types=["cell.message.received"],
)
print("Webhook secret:", wh.secret)

# Phase 8: First send
client.cells.messages.send(
    cell.cell_id,
    to="+15559876543",
    body="Hi! This is Acme Corp. You opted in for updates. Reply STOP to unsubscribe.",
    request_options={"additional_headers": {"Idempotency-Key": "first-msg-v1"}},
)

# Phase 9: Reply (when message received via webhook or poll)
messages = client.cells.messages.list(cell.cell_id, labels=["unread"])
if messages.messages:
    msg = messages.messages[0]
    client.cells.messages.reply(cell.cell_id, msg.message_id, body="Thanks! We'll help shortly.")
    client.cells.messages.update(cell.cell_id, msg.message_id, add_labels=["read"], remove_labels=["unread"])

TypeScript

/**
 * AgentCell full onboarding — copy into Cursor/Claude.
 */
import { AgentCellClient } from "@agentcell/sdk";

async function onboard() {
  const anon = new AgentCellClient({});
  const resp = await anon.agent.signUp({
    humanPhone: "+15551234567",
    humanEmail: "[email protected]",
    username: "my-agent",
  });

  const client = new AgentCellClient({ apiKey: resp.apiKey });
  await client.agent.verify({ otpCode: "123456" });

  // Phase 4: Payment — Stripe OR x402 OR MPP
  // Stripe (human):
  const checkout = await client.billing.createCheckout({ tier: "pro", ... });
  // x402 (autonomous):
  // await client.billing.payWithX402({ intent: "setup", tier: "pro" });
  // MPP (autonomous):
  // await client.billing.payWithMpp({ intent: "setup", tier: "pro", method: "tempo" });

  const cell = await client.cells.create({
    displayName: "My Agent Cell",
    areaCode: "415",
    clientId: "my-agent-cell-v1",
  });

  await client.webhooks.create({
    url: "https://your-server.com/webhook",
    eventTypes: ["cell.message.received"],
  });

  await client.cells.messages.send(
    cell.cellId,
    {
      to: "+15559876543",
      body: "Hi! This is Acme Corp. Reply STOP to unsubscribe.",
    },
    { headers: { "Idempotency-Key": "first-msg-v1" } }
  );
}

onboard();

Bash (CLI)

#!/bin/bash
set -e

# Phase 2–3
agentcell agent sign-up \
  --human-phone +15551234567 \
  --human-email [email protected] \
  --username my-agent

export AGENTCELL_API_KEY="ac_..."  # from sign-up output
agentcell agent verify --otp-code 123456

# Phase 4
CHECKOUT=$(agentcell billing checkout --tier pro --json)
echo "Open checkout URL from JSON output, then press Enter"
read

# Phase 5–8 (complete external 10DLC/A2P with your carrier before US outbound)
CELL=$(agentcell cells create --display-name "My Agent" --area-code 415 --client-id cell-v1 --json)
CELL_ID=$(echo "$CELL" | jq -r .cell_id)

agentcell webhooks create --url https://your-server.com/webhook --event-types cell.message.received

agentcell cells messages send \
  --cell-id "$CELL_ID" \
  --to +15559876543 \
  --body "Hi! This is Acme Corp. Reply STOP to unsubscribe."

10. Production Checklist

Before going live:

  • [ ] OTP verified (Phase 3)
  • [ ] Payment active — Stripe subscription, prepaid balance, or x402/MPP-funded setup (Phase 4)
  • [ ] Human knows how to reach console (magic link or /login) — can view agent status & activity
  • [ ] Cell online (device_status: online)
  • [ ] Your external 10DLC/A2P covers each US outbound cell (Phase 6 — not AgentCell)
  • [ ] Webhook verified with test event OR WebSocket connected
  • [ ] Webhook signature verification implemented
  • [ ] Idempotency on sends (Idempotency-Key)
  • [ ] Read/unread labels to prevent duplicate processing
  • [ ] Messaging settings configured if using STOP footer / ignore lists (Phase 10)
  • [ ] Pod TCPA quiet hours configured for campaign pods (Phase 10); direct replies omit pod_id when bypass intended
  • [ ] Pod cycle jobs monitored via get_pod_cycle_job or pod.cycle.* webhooks
  • [ ] Lists configured (block known spam, allow test numbers)
  • [ ] First-message template includes brand + opt-in + STOP
  • [ ] Usage alerts configured (get_usage / console)
  • [ ] Error handling for 402, 403, 429 codes
  • [ ] Human-in-the-loop drafts for sensitive replies (optional)

Related documents

| Document | Purpose | |----------|---------| | AGENTCELL_PLATFORM_SPEC.md | API, MCP, CLI, PostgreSQL/GORM, DigitalOcean | | AGENTCELL_FRONTEND_CONSOLE.md | Console portal pages and wireframes | | AGENTCELL_CONCEPT.md | Product vision and pricing | | AGENTCELL_ADMIN.md | Operator portal, phone keys, physical device provisioning | | AGENTCELL_OWNERSHIP.md | Phone/SIM/number ownership, shipping, reinstatement, forfeiture | | AGENTMAIL_BREAKDOWN.md | AgentMail patterns (sign-up, idempotency) | | AGENTPHONE_BREAKDOWN.md | Carrier limits and webhook patterns (10DLC background; AgentPhone registers in-product, AgentCell does not) |

Copy for Cursor / Claude
Follow https://agentcell.store/docs/agent-onboarding.md
Phases: discover → sign-up → verify → pay (Stripe|x402|MPP) → create_cell → user 10DLC → webhook/WSS → first send → first receive → operate.
MCP: https://mcp.agentcell.store/mcp
Keep AGENTCELL_API_KEY server-side.