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

# Metadata and saved cards

> Attach application identifiers to Stripe objects and prepare a payment method for future use.

Your server can include Stripe metadata and future-payment options when creating a Bridge session. Add them inside the request's `checkout` object, alongside `mode` and `line_items`.

These options work with hosted and embedded address collection and with automatic or manual confirmation. They are fixed when the session is created and preserved on retries. Omitting them keeps the existing checkout defaults; no API-version change is required.

## Supported fields

| Field inside `checkout`                  | Supported values                                     | Checkout mode               |
| ---------------------------------------- | ---------------------------------------------------- | --------------------------- |
| `metadata`                               | String-to-string map for the Stripe Checkout Session | `payment` or `subscription` |
| `payment_intent_data.metadata`           | String-to-string map for the Stripe PaymentIntent    | `payment`                   |
| `payment_intent_data.setup_future_usage` | `on_session` or `off_session`                        | `payment`                   |
| `customer_creation`                      | `always` or `if_required`                            | `payment`                   |

Only `metadata` and `setup_future_usage` are supported inside `payment_intent_data`. Other Stripe PaymentIntent settings, including manual capture, transfer settings, and application fees, remain unsupported.

## Track the Checkout Session and payment separately

`checkout.metadata` is attached to the **Stripe Checkout Session**. It is not automatically copied to a PaymentIntent or Subscription. Use `checkout.payment_intent_data.metadata` when your payment processing or reconciliation reads metadata from the **Stripe PaymentIntent**.

For example, the following checkout options attach an order ID to the Session and a payment reference to the PaymentIntent:

```json theme={null}
{
  "metadata": {
    "order_id": "order_8421"
  },
  "payment_intent_data": {
    "metadata": {
      "payment_reference": "payment_8421"
    }
  }
}
```

Add this object inside `checkout` in your create request. The Bridge's top-level `external_reference` remains a Numeral reference; it does not populate your Stripe metadata.

See [Stripe's metadata guide](https://docs.stripe.com/metadata) for how metadata is exposed on Stripe objects and events.

### Metadata limits

| Constraint            | Checkout Session metadata      | PaymentIntent metadata         |
| --------------------- | ------------------------------ | ------------------------------ |
| Merchant keys         | At most 45                     | At most 50                     |
| Key length            | 1–40 characters                | 1–40 characters                |
| Value type and length | String, at most 500 characters | String, at most 500 characters |

Keys cannot contain `[` or `]`, or start with the reserved `numeral_` prefix. Numeral reserves five of Stripe's 50 Session metadata keys for checkout correlation. Session and PaymentIntent metadata are validated independently.

Use application identifiers in metadata. Do not include payment credentials or other sensitive information. Merchant metadata is omitted from the Bridge's browser-facing session responses and collector events.

## Save a card for future payments

In payment mode, set `payment_intent_data.setup_future_usage` to indicate how you intend to use the payment method later:

* `off_session`: future payments when the customer is not actively checking out.
* `on_session`: future payments while the customer is present.

To have Stripe attach the payment method to a Customer after a successful payment, choose one of these options:

| Customer situation                                | What to send                           |
| ------------------------------------------------- | -------------------------------------- |
| You already have a Stripe Customer                | `checkout.customer: "cus_123"`         |
| Stripe should create a Customer for this checkout | `checkout.customer_creation: "always"` |

Do not send `customer` and `customer_creation` together. `customer_creation: "if_required"` is accepted but does not guarantee a Customer for an ordinary one-time payment. An email address alone does not select or create the Customer needed for automatic attachment.

If you omit both Customer options, the payment method is not automatically attached to a Customer. Use an existing Customer or `customer_creation: "always"` for the flow above.

Saving a payment method does not schedule a future charge. Your application manages later payments through Stripe. Future payments can still require authentication or fail. See [Stripe's guide to saving payment details](https://docs.stripe.com/payments/checkout/save-during-payment?payment-ui=stripe-hosted).

## Combine tracking, promotion codes, and saved cards

This server-side request creates a payment checkout with separate Session and PaymentIntent metadata, buyer-entered promotion codes, and off-session setup for a new Stripe Customer:

```bash theme={null}
curl https://api.numeralhq.com/tax/bridge/sessions \
  -H "Authorization: Bearer $NUMERAL_API_KEY" \
  -H "X-API-Version: 2026-03-01" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: checkout_order_8421" \
  -d '{
    "config_id": "brcfg_123",
    "collection_mode": "hosted",
    "confirmation_method": "automatic",
    "external_reference": "order_8421",
    "checkout": {
      "mode": "payment",
      "line_items": [{ "price": "price_123", "quantity": 1 }],
      "success_url": "https://store.example/success",
      "cancel_url": "https://store.example/cart",
      "metadata": {
        "order_id": "order_8421"
      },
      "allow_promotion_codes": true,
      "customer_creation": "always",
      "payment_intent_data": {
        "setup_future_usage": "off_session",
        "metadata": {
          "payment_reference": "payment_8421"
        }
      }
    }
  }'
```

Use your own configuration and Price IDs, with redirect URLs allowed by the configuration. Use a new idempotency key for each logical checkout; keep it unchanged for retries. Replace `customer_creation` with `customer` to save the method to an existing Stripe Customer.

The configuration supplies the tax-location policy. If the address is missing, the returned URL collects it before continuing to Stripe. Promotion-code availability depends on the cart's tax rules; see [Discounts and promotion codes](/integrations/stripe/stripe-checkout-discounts).

<Note>
  These are fields in `checkout` for the REST endpoint and `numeral.tax.bridge.sessions.create(...)`. Do not put them at the top level of that request. If your installed SDK does not yet expose a new field, use the REST request shown above.
</Note>

## Embedded collection and browser presets

Set these fields on the authenticated **server create request**, then pass only the session ID and session-scoped capability to the embedded collector. The browser collector continues the session with the saved options; it does not need the merchant metadata.

Publishable-key browser preset creates cannot supply metadata or saved-card options. Create the session on your server when you need them. See [Embed address collection](/integrations/stripe/stripe-checkout-embedded).

## Limits to plan for

* `payment_intent_data` and `customer_creation` are supported only in `payment` mode. Subscription Checkout already saves its payment method for renewals; Session metadata is supported in subscription mode.
* Bridge does not accept subscription trial settings or `mode: "setup"`. These additions do not enable a trial or a card-only checkout.
* A zero-dollar payment checkout does not collect a card or create a PaymentIntent, including when a promotion code discounts the entire purchase. `setup_future_usage` does not change that behavior.
* `saved_payment_method_options` is not supported. Preparing a card for future charges does not by itself guarantee that Stripe will display it in a later Checkout Session.

## Verify your integration

Use a test-mode configuration and connected Stripe account. Complete a non-zero test payment, then inspect Stripe to confirm:

1. The Checkout Session contains your Session metadata.
2. The PaymentIntent contains its separate metadata and the expected `setup_future_usage`.
3. The payment method is attached to the intended Customer.
4. Your application can perform its intended future-payment flow in test mode.

Also test existing checkout requests with these options omitted and a zero-dollar order if your discounts permit one.
