> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Addresses

> Addresses, countries, states, and zones — how geography drives checkout, taxes, and shipping

## Overview

Geography is central to how Spree handles checkout, pricing, taxes, and shipping. The system works through a chain of related concepts:

```
Markets → Countries → Zones → Tax Rates & Shipping Methods
                  ↘ States
                  ↘ Addresses
```

* [**Markets**](/developer/core-concepts/markets) group countries into selling regions with their own currency and locale
* **Countries** and **States** provide the geographic data for addresses
* **Zones** group countries or states together to define where tax rates and shipping methods apply
* **Addresses** tie a customer to a specific location, determining which zones — and therefore which taxes and shipping options — apply to their order

## Addresses

An address represents a shipping or billing location. Every order has a shipping address and a billing address, and customers can save multiple addresses in their address book.

| Field                     | Description                                                               |
| ------------------------- | ------------------------------------------------------------------------- |
| `first_name`, `last_name` | Contact name                                                              |
| `address1`, `address2`    | Street address                                                            |
| `city`                    | City                                                                      |
| `postal_code`             | Postal code (not required for all countries)                              |
| `phone`                   | Phone number                                                              |
| `company`                 | Company name (optional)                                                   |
| `label`                   | User-facing label like "Home" or "Office" (optional, unique per customer) |
| `country_iso`             | Country (ISO alpha-2 code, e.g., `US`)                                    |
| `state_abbr`              | State/province abbreviation (required for some countries, e.g., `CA`)     |

Whether a state or zipcode is required depends on the country. For example, the US requires both, while Hong Kong requires neither. The API returns `states_required` and `zipcode_required` on each country so your frontend can adapt the form dynamically.

### Customer Address Book

Customers can save multiple addresses and set a default for shipping and billing. When a customer completes checkout, the selected addresses are cloned onto the order — so editing an address later doesn't change past orders.

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  // List addresses
  const { data: addresses } = await client.customer.addresses.list()

  // Create an address
  const address = await client.customer.addresses.create({
    first_name: 'John',
    last_name: 'Doe',
    address1: '123 Main St',
    city: 'Los Angeles',
    country_iso: 'US',
    state_abbr: 'CA',
    postal_code: '90001',
    phone: '555-0100',
  })

  // Update an address
  await client.customer.addresses.update('addr_xxx', { city: 'Brooklyn' })

  // Delete an address
  await client.customer.addresses.delete('addr_xxx')

  // Set as default shipping or billing address
  await client.customer.addresses.markAsDefault('addr_xxx', 'shipping')
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # List addresses
  curl 'https://api.mystore.com/api/v3/store/customer/addresses' \
    -H 'Authorization: Bearer <jwt_token>'

  # Create an address
  curl -X POST 'https://api.mystore.com/api/v3/store/customer/addresses' \
    -H 'Authorization: Bearer <jwt_token>' \
    -H 'Content-Type: application/json' \
    -d '{
      "first_name": "John",
      "last_name": "Doe",
      "address1": "123 Main St",
      "city": "Los Angeles",
      "country_iso": "US",
      "state_abbr": "CA",
      "postal_code": "90001",
      "phone": "555-0100"
    }'

  # Update an address
  curl -X PATCH 'https://api.mystore.com/api/v3/store/customer/addresses/addr_xxx' \
    -H 'Authorization: Bearer <jwt_token>' \
    -H 'Content-Type: application/json' \
    -d '{ "city": "Brooklyn" }'

  # Delete an address
  curl -X DELETE 'https://api.mystore.com/api/v3/store/customer/addresses/addr_xxx' \
    -H 'Authorization: Bearer <jwt_token>'
  ```
</CodeGroup>

### Checkout Addresses

During checkout, you can either reference a saved address by ID or pass a new address inline:

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  // Use saved addresses
  await client.carts.update(cartId, {
    shipping_address_id: 'addr_xxx',
    billing_address_id: 'addr_yyy',
  })

  // Or pass new addresses inline
  await client.carts.update(cartId, {
    shipping_address: {
      first_name: 'John',
      last_name: 'Doe',
      address1: '123 Main St',
      city: 'Los Angeles',
      country_iso: 'US',
      state_abbr: 'CA',
      postal_code: '90001',
      phone: '555-0100',
    },
  })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # Use a saved address
  curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
    -H 'Authorization: Bearer pk_xxx' \
    -H 'X-Spree-Token: order_token' \
    -H 'Content-Type: application/json' \
    -d '{ "shipping_address_id": "addr_xxx", "billing_address_id": "addr_yyy" }'

  # Or pass a new address inline
  curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
    -H 'Authorization: Bearer pk_xxx' \
    -H 'X-Spree-Token: order_token' \
    -H 'Content-Type: application/json' \
    -d '{
      "shipping_address": {
        "first_name": "John",
        "last_name": "Doe",
        "address1": "123 Main St",
        "city": "Los Angeles",
        "country_iso": "US",
        "state_abbr": "CA",
        "postal_code": "90001",
        "phone": "555-0100"
      }
    }'
  ```
</CodeGroup>

## Countries

Countries are the foundation of Spree's geographic system. They connect to [Markets](/developer/core-concepts/markets), contain states, and belong to zones.

Each country includes metadata that drives address form behavior:

| Field              | Description                                                  | Example         |
| ------------------ | ------------------------------------------------------------ | --------------- |
| `iso`              | ISO 3166-1 alpha-2 code                                      | `US`            |
| `iso3`             | ISO 3166-1 alpha-3 code                                      | `USA`           |
| `name`             | Country name                                                 | `United States` |
| `states_required`  | Whether the address form should show a state/province picker | `true`          |
| `zipcode_required` | Whether the address form should require a postal code        | `true`          |

### Which Countries Are Available?

Only countries assigned to a [Market](/developer/core-concepts/markets) are available during checkout. This lets you control exactly where you sell.

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  // List all countries available in this store
  const { data: countries } = await client.countries.list()

  // Get a country with its states (for address form dropdowns)
  const usa = await client.countries.get('US', { include: 'states' })
  // usa.states => [{ name: "Alabama", abbr: "AL" }, { name: "Alaska", abbr: "AK" }, ...]

  // Get a country with its market (for currency/locale resolution)
  const germany = await client.countries.get('DE', { include: 'market' })
  // germany.market => { currency: "EUR", default_locale: "de", tax_inclusive: true }
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # List all countries
  curl 'https://api.mystore.com/api/v3/store/countries' \
    -H 'Authorization: Bearer pk_xxx'

  # Get a country with states
  curl 'https://api.mystore.com/api/v3/store/countries/US?include=states' \
    -H 'Authorization: Bearer pk_xxx'

  # Get a country with its market
  curl 'https://api.mystore.com/api/v3/store/countries/DE?include=market' \
    -H 'Authorization: Bearer pk_xxx'
  ```
</CodeGroup>

Use the `states_required` and `zipcode_required` fields to build adaptive address forms — show a state picker only when needed, and skip the zipcode field for countries that don't use them.

## States

States (provinces, regions) belong to a country and are used for address validation and zone matching. Countries like the US, Canada, Australia, and India have predefined states — for these countries, customers must select a state from the list rather than typing a name.

States are fetched via the country endpoint using `?include=states`:

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  const usa = await client.countries.get('US', { include: 'states' })

  // Build a state picker from the response
  usa.states.forEach(state => {
    console.log(state.abbr, state.name) // "AL", "Alabama"
  })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl 'https://api.mystore.com/api/v3/store/countries/US?include=states' \
    -H 'Authorization: Bearer pk_xxx'
  ```
</CodeGroup>

For countries without predefined states, addresses accept a free-text `state_name` field instead of `state_abbr`.

## Zones

Zones group countries or states together for [tax](/developer/core-concepts/taxes) and [shipping](/developer/core-concepts/shipments) rules. A zone is either **country-based** or **state-based**.

**Examples:**

* **EU VAT** (country zone) — Germany, France, Italy, Spain, ... → applies EU VAT rates
* **California** (state zone) — CA → applies California sales tax
* **Domestic Shipping** (country zone) — US, CA → enables domestic shipping methods

When a customer enters their address at checkout, Spree matches it against zones to determine:

1. Which **tax rates** apply (see [Taxes](/developer/core-concepts/taxes))
2. Which **shipping methods** are available (see [Shipments](/developer/core-concepts/shipments))

Zones are configured in the admin dashboard — storefront developers don't interact with them directly via the API.

### Tax Zones and Markets

Each [Market](/developer/core-concepts/markets) resolves a tax zone from its default country. This means product prices display the correct tax treatment (inclusive or exclusive) before the customer enters an address — just from knowing their market.

## How It All Fits Together

Here's how geography flows through a typical checkout:

1. **Customer visits the store** — their country is detected (from URL, geolocation, or selection)
2. **Market resolved** — the country maps to a market, which sets the currency and locale
3. **Products displayed** — prices use the market's currency and tax zone for correct formatting
4. **Customer enters address** — the address form adapts based on `states_required` and `zipcode_required`
5. **Zones matched** — the shipping address determines which tax rates and shipping methods apply
6. **Order completed** — the address is cloned onto the order for permanent record

## Related Documentation

* [Markets](/developer/core-concepts/markets) — Multi-region commerce with currency, locale, and country grouping
* [Taxes](/developer/core-concepts/taxes) — How zones and addresses affect taxation
* [Shipments](/developer/core-concepts/shipments) — How zones and addresses affect shipping availability
* [Orders](/developer/core-concepts/orders) — Order billing and shipping addresses
