> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://agentphone.to/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://agentphone.to/docs/_mcp/server.

# Sub-Accounts

> Create isolated sub-accounts for separate campaigns, brands, or clients under one master account.

Sub-accounts let you run multiple isolated environments under a single master account. Each sub-account gets its own agents, phone numbers, conversations, calls, webhooks, and 10DLC registration, while sharing the master account's billing wallet and API key.

## When to use sub-accounts

* **Multiple 10DLC campaigns** (e.g. Marketing vs. Customer Care)
* **Multi-brand support** (separate phone presence per brand)
* **Client isolation** (agencies managing multiple clients)
* **Dev/staging environments** alongside production

## How it works

A sub-account is a fully isolated account linked to a parent. Every feature (agents, numbers, messages, calls, webhooks) is scoped to the sub-account. Billing draws from the parent's wallet.

```
Master Account (billing, API keys)
├── Sub-Account "Marketing"  (own agents, numbers, messages, calls)
├── Sub-Account "Support"    (own agents, numbers, messages, calls)
└── Sub-Account "Client X"   (own agents, numbers, messages, calls)
```

## Create a sub-account

```typescript
import { AgentPhoneClient } from "agentphone";
const client = new AgentPhoneClient({ token: process.env.AGENTPHONE_API_KEY!, maxRetries: 0 });

const sub = await client.subAccounts.createSubAccount({ name: "Marketing" });
if (!sub || typeof sub !== "object" || !("id" in sub) || typeof sub.id !== "string") {
  throw new Error("Expected a sub-account ID");
}
const subId = sub.id;
console.log(subId);
```

```python
from agentphone import AgentPhone
client = AgentPhone(api_key="sk_live_...")

sub = client.sub_accounts.create(name="Marketing")
sub_id = sub["id"]  # this method returns a dict
print(sub_id)
```

```bash
curl -X POST https://api.agentphone.ai/v1/sub-accounts \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Marketing"}'
```

## Target a sub-account with `X-Sub-Account-Id`

Use your master API key with the `X-Sub-Account-Id` header to operate on any sub-account. Scope agents, numbers, messages, calls, and webhooks consistently. Most requests without the header target the master account; registration status can resolve a child campaign, so pass the header explicitly when diagnosing it. Billing and API-key management remain on the master account.

```typescript
// List numbers in the "Marketing" sub-account
const numbers = await client.numbers.listNumbers({}, {
  headers: { "X-Sub-Account-Id": subId },
  queryParams: { limit: 20 },
});
```

```python
# Python 0.20.1 has no public per-request header option; use HTTP.
import os
import requests

response = requests.get(
    "https://api.agentphone.ai/v1/numbers",
    headers={
        "Authorization": f"Bearer {os.environ['AGENTPHONE_API_KEY']}",
        "X-Sub-Account-Id": sub_id,
    },
    params={"limit": 20},
    timeout=30,
)
response.raise_for_status()
numbers = response.json()
```

```bash
# List numbers in the "Marketing" sub-account
curl https://api.agentphone.ai/v1/numbers \
  -H "Authorization: Bearer sk_live_..." \
  -H "X-Sub-Account-Id: cmps2uxc5000536awd6zu8rtr"
```

### Example: full workflow

Create the sub-account, then create its agent and number with the same header. The number purchase below incurs its provisioning charge. Requires `curl` and `jq`.

```bash
set -euo pipefail
: "${AGENTPHONE_API_KEY:?Set AGENTPHONE_API_KEY}"
API=https://api.agentphone.ai
SUB_ID=$(curl --fail-with-body -sS "$API/v1/sub-accounts" \
  -H "Authorization: Bearer $AGENTPHONE_API_KEY" -H 'Content-Type: application/json' \
  -d '{"name":"Marketing"}' | jq -er '.id')
AGENT_ID=$(curl --fail-with-body -sS "$API/v1/agents" \
  -H "Authorization: Bearer $AGENTPHONE_API_KEY" -H "X-Sub-Account-Id: $SUB_ID" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Marketing Bot","voiceMode":"hosted","systemPrompt":"Help callers with product questions."}' | jq -er '.id')
curl --fail-with-body -sS "$API/v1/numbers" \
  -H "Authorization: Bearer $AGENTPHONE_API_KEY" -H "X-Sub-Account-Id: $SUB_ID" \
  -H 'Content-Type: application/json' \
  -d "$(jq -n --arg agent "$AGENT_ID" '{country:"US",agentId:$agent}')"
```

Complete [SMS registration](/docs/sms-registration) in this same account scope before outbound SMS. A registration submitted from the parent creates another sub-account by default; do not accidentally register a different campaign environment.

## What's shared vs. isolated

| Feature                  | Shared with parent | Isolated per sub-account |
| ------------------------ | ------------------ | ------------------------ |
| Billing wallet (credits) | Yes                | -                        |
| API keys                 | Yes                | -                        |
| Team members             | Yes                | -                        |
| Agents                   | -                  | Yes                      |
| Phone numbers            | -                  | Yes                      |
| Conversations & messages | -                  | Yes                      |
| Voice calls              | -                  | Yes                      |
| Webhooks                 | -                  | Yes                      |
| 10DLC registration       | -                  | Yes                      |
| Contacts                 | -                  | Yes                      |

## Limits

* Maximum **500 sub-accounts** per master account
* Sub-accounts cannot create their own sub-accounts (one level only)
* Sub-accounts cannot create API keys or modify billing settings

## Dashboard access

Sub-accounts are also accessible from the AgentPhone dashboard:

1. Go to **Settings** on the master account
2. Find the **Sub-Accounts** section
3. Click **Create** to add a new sub-account
4. Click any sub-account to switch into it and see its full dashboard
5. Use the **"Back to main account"** banner to return