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

# Customer location and address validation

> Choose between a complete address, customer IP, Numeral-hosted collection, or embedded address collection.

Numeral for Stripe Checkout accepts the best customer location signal your application already has. You can send a complete address, send the customer's public IP address, or provide a country and let Numeral collect only the missing fields.

| Integration path      | What your server sends                                                     | Buyer experience                                                                      |
| --------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Complete address      | Country and the available street, city, state or province, and postal code | Usually continues directly to Stripe                                                  |
| Customer IP           | The customer's public IPv4 or IPv6 address                                 | Usually continues directly to Stripe when the IP resolves confidently                 |
| Numeral hosted        | A country or partial address with `collection_mode: "hosted"`              | Numeral collects missing fields on `checkout.numeralhq.com`, then continues to Stripe |
| Embedded on your site | A country or partial address with `collection_mode: "embedded"`            | The secure Numeral collector appears inside your checkout                             |

## Address validation

Numeral validates customer location before finalizing tax. For example, a New York postal code paired with California as the state is not silently accepted as a taxing jurisdiction.

* State or province and postal code are collected together where both are needed.
* Mismatches remain correctable in the Numeral collector instead of ending the checkout.
* Numeral asks only for fields the tax calculation still requires.
* If a merchant-provided address is invalid, the server receives a structured API error that can be shown in the merchant's own address form.
* Buyer address and tax ID values are not included in merchant-facing collector events.

<Note>
  Use ISO 3166-1 alpha-2 country codes such as `US`, `CA`, `GB`, or `DE`. Use the standard state, province, or region abbreviation when one exists.
</Note>

## Send a complete address

Use the address path when your application already collects billing, shipping, or service address information.

```ts theme={null}
tax_context: {
  location: {
    basis: "shipping_address",
    assurance: "self_attested",
    address: {
      country: "US",
      line_1: "123 W 31st St",
      city: "New York",
      province: "NY",
      postal_code: "10001",
    },
  },
}
```

Choose the `basis` that matches how your configuration and business establish the place of sale:

* `billing_address`
* `shipping_address`
* `service_address`
* `merchant_asserted`

When this address resolves successfully, Numeral calculates tax and the session `url` normally points directly to Stripe Checkout.

## Send the customer IP

If your server knows the customer's public IP address, send it as an alternative to `address`. Do not send both in the same location object.

```ts theme={null}
const customerIp = getCustomerIpFromTrustedProxy(request);

const session = await numeral.tax.bridge.sessions.create({
  config_id: process.env.NUMERAL_STRIPE_CHECKOUT_CONFIG_ID!,
  collection_mode: "hosted",
  confirmation_method: "automatic",
  checkout: {
    mode: "payment",
    line_items: [{ price: "price_123", quantity: 1 }],
    success_url: "https://store.example/success",
    cancel_url: "https://store.example/cart",
  },
  tax_context: {
    location: {
      basis: "billing_address",
      ip: { value: customerIp },
    },
  },
  "X-API-Version": "2026-03-01",
  "Idempotency-Key": crypto.randomUUID(),
});
```

If IP resolution provides enough location data, the buyer can continue directly to Stripe without entering an address. If it does not, the selected `collection_mode` obtains the missing information.

<Warning>
  Capture the buyer's IP on your server from a trusted platform or proxy header. Do not send your server's outbound IP, and do not trust an arbitrary IP value submitted by browser JavaScript.
</Warning>

## Numeral-hosted collection

Hosted collection is the simplest fallback when your checkout does not collect an address. Send the known country or partial address and set `collection_mode` to `hosted`.

```ts theme={null}
const session = await numeral.tax.bridge.sessions.create({
  config_id: process.env.NUMERAL_STRIPE_CHECKOUT_CONFIG_ID!,
  collection_mode: "hosted",
  confirmation_method: "automatic",
  checkout: {
    mode: "payment",
    line_items: [{ price: "price_123", quantity: 1 }],
    success_url: "https://store.example/success",
    cancel_url: "https://store.example/cart",
  },
  tax_context: {
    location: {
      basis: "billing_address",
      address: { country: "US" },
    },
  },
  "X-API-Version": "2026-03-01",
  "Idempotency-Key": crypto.randomUUID(),
});

response.redirect(303, session.url!);
```

The buyer is sent to a Numeral-hosted address validation step and then automatically continues to Stripe Checkout. The returned URL is stable for idempotent replay and does not contain a session capability or buyer information.

<Tip>
  Redirect to `session.url` without inspecting whether it points to Numeral or Stripe. This keeps the fast path and collection fallback identical in your application code.
</Tip>

## Embedded collection on your site

Embedded mode keeps the location step inside your checkout. Your server creates the session, then passes only the session ID and session-scoped `client_secret` to your browser.

```ts theme={null}
const session = await numeral.tax.bridge.sessions.create({
  config_id: process.env.NUMERAL_STRIPE_CHECKOUT_CONFIG_ID!,
  collection_mode: "embedded",
  confirmation_method: "automatic",
  checkout: {
    mode: "payment",
    line_items: [{ price: "price_123", quantity: 1 }],
    success_url: "https://store.example/success",
    cancel_url: "https://store.example/cart",
  },
  tax_context: {
    location: {
      basis: "billing_address",
      address: { country: "US" },
    },
  },
  "X-API-Version": "2026-03-01",
  "Idempotency-Key": crypto.randomUUID(),
});

return Response.json({
  sessionId: session.id,
  clientSecret: session.client_secret,
});
```

Continue with [Embed address collection](/integrations/stripe/stripe-checkout-embedded) to mount the collector and handle its events.

## Selecting the right path

<AccordionGroup>
  <Accordion title="My checkout already collects a full address">
    Send the address in the initial request. This gives the fastest buyer experience and lets Numeral validate the address before Stripe Checkout is created.
  </Accordion>

  <Accordion title="I know the customer's public IP but do not collect an address">
    Send `tax_context.location.ip`. Choose hosted or embedded collection as the fallback in case the IP does not resolve with enough confidence.
  </Accordion>

  <Accordion title="I want the least frontend work">
    Use hosted collection. Your application only redirects to the opaque URL returned by Numeral.
  </Accordion>

  <Accordion title="I want address collection to remain inside my checkout">
    Use embedded collection. The Numeral custom element renders a secure cross-origin iframe and exposes redacted lifecycle events to your page.
  </Accordion>
</AccordionGroup>
