# Purchasing Phone Numbers

> Search for and purchase phone numbers to send messages

Phone numbers are required to send SMS and WhatsApp messages. Zavu lets you search for available numbers and purchase them directly through the API or dashboard.

[Video: How to buy a phone number](https://youtu.be/u17WYksKD4U?si=oKHyyUbxs_5cpMx7)

## Plans and the Included Number

Buying phone numbers requires a paid plan: on the Free plan the purchase is refused with `402 paid_plan_required`. A paid plan includes one number at no charge, once per account: it must be a US or Canadian number (a +1 number) costing $20 a month or less. The included number is one per account, across every team its owner owns, and is granted once: releasing it does not make another number free. Search results mark the numbers that qualify with `pricing.isFreeEligible`.

## Searching for Available Numbers

Before purchasing, search for available numbers in your target country:

```typescript
const result = await zavu.phoneNumbers.searchAvailable({
  countryCode: "US",
  type: "local",
  limit: 10,
});

for (const number of result.items) {
  console.log(number.phoneNumber, number.locality, number.region);
  console.log("Monthly price:", number.pricing.monthlyPrice);
  console.log("Free eligible:", number.pricing.isFreeEligible);
}
```

```bash
curl "https://api.zavu.dev/v1/phone-numbers/available?countryCode=US&type=local&limit=10" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"
```

### Search Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `countryCode` | string | Yes | Two-letter ISO country code (e.g., "US", "GB") |
| `type` | string | No | Number type: `local`, `national`, `mobile`, or `tollFree` (default: `local`) |
| `contains` | string | No | Search for numbers containing this pattern (e.g., "555") |
| `limit` | integer | No | Max results to return (default: 10, max: 50) |

### Response

```json
{
  "items": [
    {
      "phoneNumber": "+14155551234",
      "friendlyName": "(415) 555-1234",
      "locality": "San Francisco",
      "region": "CA",
      "capabilities": {
        "sms": true,
        "voice": true,
        "mms": true
      },
      "pricing": {
        "monthlyPrice": 1.25,
        "upfrontPrice": 1.00,
        "isFreeEligible": true
      }
    }
  ]
}
```

### Empty results and errors

| Response | Meaning |
|----------|---------|
| `200` with empty `items` | The country is served, but nothing matched these filters: no stock of this `type`, or no number containing these digits. A `type` the country does not sell answers this way too: retry with another `type`. |
| `400 country_restricted` | The country is not sold self-service. The message names who to contact. |
| `400 invalid_request` with `details.field: "contains"` | The inventory refused the `contains` pattern itself. A pattern that only matched nothing is answered `200` with empty `items`. |
| `404 country_unavailable` | No numbers are stocked in this country. |
| `502 inventory_unavailable` | The inventory could not be reached, or refused a search it should accept. Retry; do not treat it as no stock. |

## Regulatory Requirements

Some numbers require regulatory information (an address, a document, or text) before they can be used. Which ones is decided per number, and the purchase checks it for the exact number before charging anything. Look it up with `GET /v1/phone-numbers/requirements?phoneNumber=%2B...` before buying.

A number with requirements is bought with `type` and `regulatoryRequirements`, starts with `regulatoryStatus: pending_review`, and can send messages and place calls once it is `approved`. The [Regulatory Requirements](https://www.zavu.dev/docs/guides/phone-numbers/regulatory-requirements) guide covers:

- Looking up the requirements for a number
- Creating addresses and uploading documents
- Including requirements in your purchase request
- Reusing information submitted before
- Following review and assigning the number to a sender

## Purchasing a Phone Number

Once you've found a number you want, purchase it:

```typescript
const phoneNumber = await zavu.phoneNumbers.purchase({
  phoneNumber: "+14155551234",
  name: "Customer Support",
});

console.log("Purchased:", phoneNumber.phoneNumber.phoneNumber);
console.log("ID:", phoneNumber.phoneNumber.id);
```

```bash
curl -X POST https://api.zavu.dev/v1/phone-numbers \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+14155551234",
    "name": "Customer Support"
  }'
```

### Purchase Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `phoneNumber` | string | Yes | Phone number in E.164 format |
| `name` | string | No | Custom name for the phone number (max 100 characters) |
| `type` | string | With `regulatoryRequirements` | The type the number was found under: `local`, `national`, `mobile`, or `tollFree`. A number not listed under it is refused with `400 number_unavailable` |
| `regulatoryRequirements` | array | For numbers with requirements | `{ requirementType, fieldValue }` entries. See [Regulatory Requirements](https://www.zavu.dev/docs/guides/phone-numbers/regulatory-requirements). Not in the SDKs yet: use REST |

### Response

```json
{
  "phoneNumber": {
    "id": "pn_abc123",
    "phoneNumber": "+14155551234",
    "name": "Customer Support",
    "capabilities": ["sms", "voice"],
    "status": "active",
    "regulatoryStatus": "approved",
    "pricing": {
      "monthlyPrice": 1.25,
      "upfrontCost": 100,
      "monthlyCost": 125,
      "isFreeNumber": true
    },
    "nextRenewalDate": "2025-02-15T00:00:00.000Z",
    "createdAt": "2025-01-15T10:30:00.000Z"
  }
}
```

> **Warning:**
> Purchasing a phone number deducts the upfront cost and the first month from your account balance. Ensure you have sufficient funds before purchasing.

## Listing Your Phone Numbers

View all phone numbers owned by your project:

```typescript
const result = await zavu.phoneNumbers.list();

for (const number of result.items) {
  console.log(number.id, number.phoneNumber, number.name);
  console.log("Status:", number.status);
}

// Filter by status
const activeNumbers = await zavu.phoneNumbers.list({
  status: "active",
});
```

```bash
curl "https://api.zavu.dev/v1/phone-numbers" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"

# Filter by status
curl "https://api.zavu.dev/v1/phone-numbers?status=active" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"
```

## Getting Phone Number Details

Retrieve details for a specific phone number:

```typescript
const { phoneNumber: number } = await zavu.phoneNumbers.retrieve("pn_abc123");

console.log(number.phoneNumber);
console.log("Assigned to sender:", number.senderId);
console.log("Next renewal:", number.nextRenewalDate);
```

```bash
curl "https://api.zavu.dev/v1/phone-numbers/pn_abc123" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"
```

## Updating a Phone Number

Update the name of a phone number:

```typescript
const number = await zavu.phoneNumbers.update("pn_abc123", {
  name: "Marketing Line",
});
```

```bash
curl -X PATCH https://api.zavu.dev/v1/phone-numbers/pn_abc123 \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Marketing Line"
  }'
```

## Assigning to a Sender

Connect a phone number to a sender profile for use in messaging. A number still under regulatory review (`regulatoryStatus: pending_review`) can be assigned too: it is connected to the sender when review approves it. A number rejected in review cannot be assigned, and the call answers `400`.

```typescript
const number = await zavu.phoneNumbers.update("pn_abc123", {
  senderId: "snd_xyz789",
});
```

```bash
curl -X PATCH https://api.zavu.dev/v1/phone-numbers/pn_abc123 \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "snd_xyz789"
  }'
```

To unassign a phone number from a sender:

```typescript
const number = await zavu.phoneNumbers.update("pn_abc123", {
  senderId: null,
});
```

## Releasing a Phone Number

Release a phone number you no longer need:

```typescript
await zavu.phoneNumbers.release("pn_abc123");
```

```bash
curl -X DELETE https://api.zavu.dev/v1/phone-numbers/pn_abc123 \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"
```

> **Warning:**
> You cannot release a phone number that is assigned to a sender. Unassign it first by setting `senderId` to `null`.

## Phone Number Statuses

| Status | Description |
|--------|-------------|
| `active` | Owned and billing. Usable for messaging when `regulatoryStatus` is also `approved` |
| `suspended` | Temporarily disabled (e.g., for payment issues) |
| `releasing` | Being released; it can no longer send |
| `released` | Released; it can no longer send |
| `pending` | Legacy. Accepted by the `status` filter, never written to a number today |

The SDK `status` enums carry `active`, `suspended` and `pending` only; read
`releasing` and `released` from the REST response until their next release.

A number on its way out carries `releaseAt`: the date it goes back to the
carrier, after a paid plan ended or at the end of the 7-day grace after a
renewal could not be paid. Paying, or returning to a paid plan, before that
date keeps it. A released number cannot be recovered.

### When a paid plan ends

Without a paid plan a team keeps **one** number:

- **Which one.** The one chosen in the dashboard when cancelling. Without a
  choice, the number the plan included; without one, the oldest number the team
  bought. Numbers you brought yourself are never released.
- **How it is paid.** Monthly from the balance, at its listed price. A number
  the plan included is charged its first month when the plan ends; a bought
  number keeps its renewal date. A renewal the balance cannot pay suspends it,
  and it is released at the end of the 7-day grace.
- **Every other number** keeps working, unbilled, and is released 7 days after
  the plan ends. `releaseAt` carries the exact date (00:00 UTC of the day after
  the window closes).
- **Coming back to a paid plan.** Before `releaseAt`, the numbers on their way
  out stay and bill as paid numbers again. The kept number is the included one
  again if it was the included one; otherwise it stays a paid number.

## Using Phone Numbers with Channels

Phone numbers can be used with different messaging channels:

### SMS
Phone numbers are directly used as the sender ID for SMS messages. Simply assign the phone number to a sender and start sending.

### WhatsApp
For WhatsApp, you need to register your phone number with WhatsApp Business API. The phone number is used to receive the verification code during WhatsApp Business Account setup.

> **Info:**
> WhatsApp Business registration requires a phone number that can receive SMS. Your Zavu phone number works perfectly for this.

## Pricing

Phone number pricing varies by country and type:

| Component | Description |
|-----------|-------------|
| `upfrontPrice` | One-time purchase cost |
| `monthlyPrice` | Recurring monthly fee |
| `isFreeEligible` | Whether this account can claim this number as the one its paid plan includes. `false` on Free, and once the benefit has been claimed, even for a number that would otherwise qualify |

> **Info:**
> Prices are displayed in USD. Monthly fees are automatically charged from your account balance.

## Best Practices

  - **Name Your Numbers**: Give descriptive names to phone numbers so you can easily identify their purpose.
  - **Monitor Status**: Regularly check the status of your phone numbers to ensure they're active.
  - **Plan Capacity**: Purchase numbers based on your messaging volume and geographic needs.
  - **Use Local Numbers**: Local numbers often have higher delivery rates than toll-free numbers for certain use cases.

## Next Steps

  - [Create a Sender](https://www.zavu.dev/docs/concepts/senders): Connect your phone number to a sender profile
  - [Send SMS](https://www.zavu.dev/docs/guides/sending-messages/sms): Start sending SMS messages
