Authentication
Agent Number uses bearer tokens issued at subscribe time, recoverable via wallet signature. Your wallet is the permanent account identity.
Account model
The wallet that paid for a subscription is the account. The phone number, the bearer token, and the subscription term are all bound to that wallet. Specifically:
- Lose your bearer token? Recover it by signing a challenge with the original wallet (see flow below).
- Lose access to the paying wallet? You cannot recover the number or remaining subscription time. There is no admin override.
- Use a durable wallet you control long-term. Don't subscribe with an ephemeral or per-session wallet.
Bearer token
Every authenticated request carries:
Authorization: Bearer <token>
Bearer-gated endpoints: /sms/send, /sms/receive, /sms/messages, /voice/dial, /voice/presence/<phone>, /voice/stream/<call_id>, /number.
Token issued by:
POST /subscribeafter a successful x402 / MPP paymentPOST /authafter a successful wallet-signature recovery (below)
Recovery flow (wallet signature)
When a token is lost, recover it without paying again by proving you control the original wallet. Two steps:
1. Get a nonce
curl -X POST https://agentnumber.really.com/auth/nonce
# → {"nonce": "abc123...", "expires_in": 300}
No body is needed — the endpoint mints a fresh nonce on every call. Wallet identity is established at the /auth step below via the signature. The nonce is single-use and expires after expires_in seconds (5 minutes). Don't cache it.
2. Sign and submit
Sign the message "Sign in to really.com SMS\nNonce: <nonce>" with the wallet's private key. Use viem, ethers, web3.py, or whatever your environment supports. Then:
curl -X POST https://agentnumber.really.com/auth \
-H "content-type: application/json" \
-d '{
"wallet": "0xYourWallet",
"nonce": "abc123...",
"signature": "0x..."
}'
# → {"token": "...", "number": "+15555550123", "expires_at": "..."}
Verification is signature-only — the wallet doesn't need to be online or hold gas. Token-rotation note: a successful recovery revokes all existing tokens for the wallet and issues a fresh one. If you have multiple agents using the same subscription, they'll all need to re-auth after a recovery.
Recovery via MCP
The same flow works through MCP tools auth_nonce and auth. Same shape, same effect.
Common errors
| Status | Body | Meaning |
|---|---|---|
401 | {"error": "unauthorized", "message": "missing bearer token"} | No Authorization header on a bearer-gated endpoint |
401 | {"error": "unauthorized", "message": "invalid, revoked, or expired token"} | Token validation failed — re-run recovery |
401 | {"error": "nonce_invalid", "message": "nonce expired, used, or unknown"} | Get a fresh nonce and retry |
401 | {"error": "signature_mismatch", "message": "signature did not recover the claimed wallet"} | Signature doesn't match the claimed wallet for the nonce |
402 | {"error": "no_active_subscription"} | No active subscription for this wallet |
402 | {"error": "subscription_expired"} | Renew via /subscribe with a new payment |
500 | {"error": "subscription_missing_slot"} | Internal: subscription has no slot binding |
500 | {"error": "slot_inventory_missing"} | Internal: slot row missing |
500 | {"error": "token_creation_failed"} | Internal: token issuance failed |