# Calculate tax in your custom payment flows Learn how to integrate taxes with the Stripe Tax and Payment Intents APIs. The Stripe Tax API enables you to calculate tax in your custom payment flows. If you use the Payment Intents API, Stripe can submit tax transactions in the payment lifecycle. > #### Choose the right tax integration > > Stripe offers two ways to handle tax in custom payment flows. Choose based on how much control you need over tax reversals: > > - Use *the Payment Intents integration* if you want Stripe to handle tax transactions and reversals automatically, and if flat-amount refund reversals meet your needs. - Use [the custom tax API](https://docs.stripe.com/tax/custom.md) if you need line-item level control over tax reversals (for example, refunding specific items), work with multiple payment processors, or need full control over when transactions are recorded. A diagram providing a high level overview of the tax api integration outlined in this doc (See full diagram at https://docs.stripe.com/tax/payment-intent) ## Calculate tax Calculating tax typically requires your customer’s location. You can: You can also use a [two-step confirmation](https://docs.stripe.com/payments/build-a-two-step-confirmation.md) integration to calculate tax with a Payment Element between the payment collection and confimation steps. - Use the [Address Element](https://docs.stripe.com/elements/address-element.md) to take advantage of autocomplete and localization features to collect your customer’s full address. This helps ensure the most accurate tax calculation. - Estimate tax based on the customer’s [IP address](https://docs.stripe.com/tax/payment-intent.md#calculate-tax). - Collect address details using your own custom form. Pass the transaction details and customer address information to the [calculate tax](https://docs.stripe.com/api/tax/calculations/create.md) API to get a new Tax `Calculation` object. ```curl curl https://api.stripe.com/v1/tax/calculations \ -u "<>:" \ -d currency=usd \ -d "line_items[0][amount]=1000" \ -d "line_items[0][reference]=L1" \ -d "line_items[0][tax_code]=txcd_99999999" \ -d "customer_details[address][line1]=920 5th Ave" \ -d "customer_details[address][city]=Seattle" \ -d "customer_details[address][state]=WA" \ -d "customer_details[address][postal_code]=98104" \ -d "customer_details[address][country]=US" \ -d "customer_details[address_source]=shipping" ``` The response includes the total amount and a tax breakdown. See the [Tax Calculation object](https://docs.stripe.com/api/tax/calculations/object.md) for the full response structure. ```json // Tax Calculation response (minimized) { "id": "taxcalc_1234567890", "amount_total": 1082, "tax_amount_exclusive": 82, "tax_amount_inclusive": 0, ... } ``` ## Link tax calculation to the PaymentIntent [Create or modify a PaymentIntent](https://docs.stripe.com/payments/quickstart.md) to include the Tax `Calculation` ID and set the `amount` to `tax_calculation.amount_total` from the [Tax Calculation](https://docs.stripe.com/api/tax/calculations/object.md) response. ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1000 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "hooks[inputs][tax][calculation]={{TAXCALCULATION_ID}}" ``` ### Supported endpoints The following endpoints support setting a calculation on a PaymentIntent. - Create: [/v1/payment_intents](https://docs.stripe.com/api/payment_intents/create.md) - Update: [/v1/payment_intents/:id](https://docs.stripe.com/api/payment_intents/update.md) - Confirm: [/v1/payment_intents/:id/confirm](https://docs.stripe.com/api/payment_intents/confirm.md) - Capture: [/v1/payment_intents/:id/capture](https://docs.stripe.com/api/payment_intents/capture.md) ### Limitations - You can only link new calculations to a PaymentIntent until it transitions to a `succeeded` state. - A tax calculation can transition to only one tax `Transaction`. If multiple PaymentIntents transition to a `succeeded` state with the same linked calculation, accounting reflects only the first one. ## Resulting Stripe actions If the PaymentIntent is correctly linked to the Tax `Calculation` object, Stripe automatically: - Creates a tax transaction from the calculation after the PaymentIntent transitions to a `succeeded` state - Performs a [flat amount](https://docs.stripe.com/tax/custom.md#reversals-partial-flat-amount) tax reversal of a tax transaction for any refunds (created with API or Dashboard) for the PaymentIntent - Creates a tax reversal for a reversal, if a refund has failed - Includes the total tax information in `PaymentIntent` receipts Stripe won’t: - Recalculate tax based on PaymentIntent changes - Change the PaymentIntent amount based on the linked tax calculation - Alter the tax transaction amount based on the PaymentIntent captured amount - Automatically create a tax reversal for disputes ## Integrate taxes for your Connect platform with the Stripe Tax and Payment Intents APIs The Payment Intents API works with connected accounts on your Connect platform. This means that if you calculate tax using a connected account, you can link the tax calculation to a PaymentIntent created using that connected account. > You can’t use destination charges if you create the tax calculation on a connected account and the PaymentIntent on the platform account. Create the tax calculation and the PaymentIntent on the same account. ## Optional: Retrieve automatically committed tax transactions Use the [/v1/tax/associations/find](https://docs.stripe.com/api/tax/associations/find.md) endpoint to retrieve information about the tax transactions that Stripe created (or failed to create) for a PaymentIntent. This allows you to verify that your integration works as intended, handle card dispute cases, or review what was created automatically. ```curl curl -G https://api.stripe.com/v1/tax/associations/find \ -u "<>:" \ -d "payment_intent={{PAYMENTINTENT_ID}}" ``` If your PaymentIntent succeeds and is refunded afterwards, you might receive the following response. > The Tax reversals are only recorded and appear in the Tax Association object after several minutes. ```json // TaxAssociation find response { "id": "taxa_1PXmsbE5ebw4kUHWxtSTF08x", "object": "tax.association", "calculation": "taxcalc_1PXmsRE5ebw4kUHW9SOln70o", "payment_intent": "pi_1PXmsSE5ebw4kUHWK7FIhQlS", "tax_transaction_attempts": [ { "source": "pi_1PXmsSE5ebw4kUHWK7FIhQlS", "status": "committed", "committed": {"transaction": "tax_1PXmsRE5ebw4kUHWLyVEiMis", } }, { "source": "re_1PXmsSE5ebw4kUHWK7FIhQlS", "status": "committed", "committed": {"transaction": "tax_1PXmsgE5ebw4kUHW7Gg8jvpX", } } ] } ``` ## See also - [Tax API for Sales Tax, GST, and VAT](https://docs.stripe.com/tax/custom.md) - [Custom payment flow guide](https://docs.stripe.com/payments/quickstart.md) - [Reporting and filing](https://docs.stripe.com/tax/reports.md) - [Use Stripe Tax with Connect](https://docs.stripe.com/tax/connect.md)