---
title: Authentication
description: Agent Number authentication — bearer tokens, wallet recovery, account model.
url: https://agentnumber.really.com/docs/auth
doc_version: "1.0.0"
last_updated: "2026-05-15"
---

> ## Documentation index
> Fetch the complete documentation index at: https://agentnumber.really.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

> **This is permanent.** Wallet loss = subscription loss. We don't custody, can't reset, can't reissue. The same property that makes the system trustless makes it unforgiving on key management.

## Bearer token

Every authenticated request carries:

```http
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 /subscribe`](/docs/payment) after a successful x402 / MPP payment
- `POST /auth` after 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

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

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

## Sitemap

- [Overview](/docs/)
- [Quickstart](/docs/quickstart)
- [Authentication](/docs/auth)
- [SMS](/docs/sms)
- [Voice](/docs/voice)
- [MCP](/docs/mcp)
- [Payment](/docs/payment)

See the full [sitemap.md](/sitemap.md) for the complete index of docs pages.

---

← Previous: [MCP](/docs/mcp) · Next: [Payment](/docs/payment) →
