# Collect tax on usage-based rate card subscriptions Learn how to calculate and collect tax on usage-based rate card subscriptions. > Rate cards are currently in [private preview](https://docs.stripe.com/release-phases.md) and could change in functionality and integration path before they’re generally available to all Stripe users. You can use Stripe Tax to calculate the tax amount on recurring payments for rate card subscriptions. To automatically handle tax calculation when your customer is ready to pay, set the customer’s location details when you create a rate card subscription. ## Activate Stripe Tax [Log in](https://dashboard.stripe.com/settings/tax) or [sign up](https://dashboard.stripe.com/register) for Stripe to activate Stripe Tax. ## Update rate cards (optional) When you create a rate card, you specify the [product tax code](https://docs.stripe.com/tax/subscriptions/rate-card-tax-codes-tax-behavior.md). If you don’t specify a code, Stripe Tax uses the default tax code selected in your [Tax Settings](https://dashboard.stripe.com/settings/tax). ## Collect customer information [Client-side] After you have an estimate of the taxes and the total, you can collect customer information, including: - Shipping address (if applicable) - Billing address - Payment details Stripe Tax collects payment details without creating a [Setup Intent](https://docs.stripe.com/api/setup_intents.md). The first step is to [create an Elements object without an Intent](https://docs.stripe.com/js/elements_object/create_without_intent): ```javascript const stripe = Stripe("<>"); const elements = stripe.elements({ mode: 'subscription', currency: '{{CURRENCY}}', amount: {{TOTAL}}, // This is the invoice total. }); ``` Next, [create an Address Element](https://docs.stripe.com/js/elements_object/create_address_element) and [a Payment Element](https://docs.stripe.com/js/elements_object/create_payment_element) and [mount](https://docs.stripe.com/js/element/mount) both: ```javascript const addressElement = elements.create('address', { mode: 'billing' // or 'shipping', if you are shipping goods }); addressElement.mount('#address-element'); const paymentElementOptions = { layout: 'accordion'}; const paymentElement = elements.create('payment', paymentElementOptions); paymentElement.mount('#payment-element'); ``` Listen to [change events](https://docs.stripe.com/js/element/events/on_change?type=paymentElement#element_on_change-event) on the Address Element. When the address changes, [re-estimate](https://docs.stripe.com/tax/subscriptions.md?estimate=after#estimate-taxes-total) the taxes and the total. ```javascript addressElement.on('change', function(event) { // Throttle your requests to avoid overloading your server or hitting // Stripe's rate limits. const { tax, total } = await updateEstimate(event.value.address); elements.update({ amount: total }); // Update your page to display the new tax and total to the user... }); ``` > When your customer is entering their address, Address Element fires a `change` event for each keystroke. To avoid overloading your server and hitting Stripe’s [rate limits](https://docs.stripe.com/rate-limits.md), wait for some time after the last `change` event before re-estimating the taxes and the total. ## Handle submission [Client-side] When your customer submits the form, call [elements.submit()](https://docs.stripe.com/js/elements/submit) to validate the form fields and collect any data required for wallets. You must wait for this function’s promise to resolve before performing any other operations. ```javascript document.querySelector("#form").addEventListener("submit", function(event) { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); const { error: submitError } = await elements.submit(); if (submitError) { // Handle error... return; } const { value: customerDetails } = await addressElement.getValue(); // See the "Save customer details" section below to implement this // server-side. await saveCustomerDetails(customerDetails); // Makes a request to your server to save the customer details. // See the "Create subscription" section below to implement this server-side. const { clientSecret } = await createSubscription(); // latest_invoice.confirmation_secret.client_secret of the new subscription. // Makes a request to your server to create a subscription. const { error: confirmError } = await stripe.confirmPayment({ elements, clientSecret, confirmParams: { return_url: {{RETURN_URL}}, // The URL Stripe redirects your customer to after they complete the payment. }, }); if (confirmError) { // Handle error... return; } // Upon a successful confirmation, your user will be redirected to the // return_url you provide before the Promise ever resolves. }); ``` ## Save customer details [Server-side] #### Customer v1 [Update](https://docs.stripe.com/api/customers/update.md) your `Customer` object using the details you’ve collected from your customer, so that Stripe Tax can determine their precise location for accurate results. > If your customer is in the United States, provide a full address if possible. We use the term “rooftop-accurate” to mean that we can attribute your customer’s location to a specific house or building. This provides greater accuracy, where two houses located side-by-side on the same street might be subject to different tax rates, because of complex jurisdiction boundaries. If you haven’t already created a `Customer` object (for example, when your customer first signs up on your website), you can [create](https://docs.stripe.com/api/customers/create.md) one now. #### Update customer ```curl curl https://api.stripe.com/v1/customers/{{CUSTOMER_ID}} \ -u "<>:" \ -d "address[line1]={{LINE1}}" \ -d "address[line2]={{LINE2}}" \ -d "address[city]={{CITY}}" \ -d "address[state]={{STATE}}" \ -d "address[postal_code]={{POSTAL_CODE}}" \ -d "address[country]={{COUNTRY}}" \ -d "tax[validate_location]=immediately" ``` > If your customer has other existing subscriptions with automatic tax enabled and you update their address information, the tax and total amounts on their future invoices might be different. This is because tax rates vary depending on customer location. #### Create customer ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d "address[line1]={{LINE1}}" \ -d "address[line2]={{LINE2}}" \ -d "address[city]={{CITY}}" \ -d "address[state]={{STATE}}" \ -d "address[postal_code]={{POSTAL_CODE}}" \ -d "address[country]={{COUNTRY}}" \ -d "tax[validate_location]=immediately" ``` Your customer must have a valid tax location in order to enable automatic tax on their subscription. Set [tax.validate_location](https://docs.stripe.com/api/customers/update.md#update_customer-tax-validate_location) to `immediately` to validate the customer’s tax location. If validation fails, Stripe fails your request with the [customer_tax_location_invalid](https://docs.stripe.com/error-codes.md#customer-tax-location-invalid) error code. Checking the [automatic_tax.status](https://docs.stripe.com/api/invoices/object.md#invoice_object-automatic_tax-status) of your preview invoices helps avoid this failure. ## Subscribe your customer to a rate card After you create a rate card, you can start subscribing customers. When you subscribe your customer to the rate card, you also define the billing cadence–how often to create invoices for your customer. You specify how to collect when you create a billing cadence: either charge automatically or send an invoice. If you charge automatically, an invoice is created and the customer’s default payment method is charged. If you send an invoice, customers receive an invoice they need to pay manually. #### Dashboard 1. Go to the Rate cards page and click the rate card you want to subscribe your customer to. 1. In the rate card details page, click the overflow menu (⋯) next to **Edit rate card**. 1. In the rate card subscription editor: - Find or add a customer. - Define the **Billing cadence**, which is how often to and when to invoice the customer. - Click **Collect tax automatically with Stripe Tax** to enable automatic Tax collection with Stripe Tax. - Click **Create subscription**. #### API ### Create a billing cadence To create a billing cadence, [create a Customer object](https://docs.stripe.com/api/customers/create.md). To test your integration and advance time, you can [create a test clock](https://docs.stripe.com/api/test_clocks/create.md) and attach it to the customer. Create a bill settings object. This will control the tax behavior on a billing cadence. ```curl curl -X POST https://api.stripe.com/v2/billing/bill_settings \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "display_name": "Re-selling configuration", "calculation": { "tax": { "type": "automatic" } } }' ``` Create a billing cadence for the customer. The `billing_cycle` defines when and how often you automatically bill the payer. When creating a billing cadence, set the exact day and time for invoicing using the following API request: ```curl curl -X POST https://api.stripe.com/v2/billing/cadences \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "payer": { "type": "customer", "customer": "{{CUSTOMER_ID}}" }, "settings": { "bill": { "id": "{{BILLING_SETTINGS_ID}}" } }, "billing_cycle": { "type": "month", "interval_count": 1, "month": { "day_of_month": 20 } } }' ``` ### Create a subscription Subscribe your customer to the rate card by passing the rate card and billing cadence in the following request. You can optionally pass a specific version of a rate card when subscribing a customer. If you don’t specify a version, the subscription applies the rate card’s live version. ```curl curl -X POST https://api.stripe.com/v2/billing/rate_card_subscriptions \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "rate_card": "rcd_A", "billing_cadence": "bc_1" }' ```