Skip to content
Create account or Sign in
The Stripe Docs logo
/
Ask AI
Create accountSign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
OverviewAccept a paymentUpgrade your integration
Online payments
OverviewFind your use case
Use Payment Links
Use a pre-built checkout page
Build a custom integration with Elements
Build an in-app integration
Use Managed PaymentsRecurring payments
In-person payments
Terminal
Payment Methods
Add payment methods
Manage payment methods
Faster checkout with Link
Payment operations
Analytics
Balances and settlement time
Compliance and security
Currencies
Declines
Disputes
Fraud prevention
Radar fraud protection
Payouts
ReceiptsRefunds and cancellations
Advanced integrations
Custom payment flows
    Overview
    Payments for existing customers
    Authorise and capture a payment separately
    Build a two-step checkout flow
    Collect payment details before creating an Intent
    Finalise payments on the server
    Take mail orders and telephone orders (MOTO)
    US and Canadian cards
    Forward card details to third-party API endpoints
    Payments line items
      Flexible payment scenarios
    Industry metadata
Flexible acquiring
Multiprocessor orchestration
Beyond payments
Incorporate your company
Crypto
Agentic commerce
Financial Connections
Climate
Verify identities
United States
English (United Kingdom)
HomePaymentsCustom payment flowsPayments line items

Use payment line items for flexible payments

Learn how to use payment line items with complex payments, such as multicapture and overcapture payments.

You can use payment line items for complex payments, such as multicapture and overcapture payments.

Multicapture

You can use payment line items during multicaptures.

Note

Multicapture isn’t supported for Klarna or PayPal.

Create and confirm an uncaptured PaymentIntent

Note

The API response doesn’t include line items by default. To return line items, expand amount_details.line_items.

Specify the capture_method as manual when creating the PaymentIntent and use the if_available parameter to request multicapture for this payment. The created PaymentIntent allows multiple captures if the payment method supports it.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount=4600 \ -d currency=usd \ -d "payment_method_types[0]"=card \ -d payment_method=pm_card_visa \ -d "payment_method_options[card][request_multicapture]"=if_available \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=200 \ -d "amount_details[tax][total_tax_amount]"=400 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=400 \ -d "amount_details[line_items][0][product_code]"=SKU001 \ -d "amount_details[line_items][0][product_name]"="Product 001" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=feet \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d "amount_details[line_items][1][product_code]"=SKU002 \ -d "amount_details[line_items][1][product_name]"="Product 002" \ -d "amount_details[line_items][1][unit_cost]"=2000 \ -d "amount_details[line_items][1][quantity]"=1 \ -d "amount_details[line_items][1][unit_of_measure]"=gallons \ -d "amount_details[line_items][1][payment_method_options][card][commodity_code]"=123123 \ -d confirm=true \ -d capture_method=manual \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items specified on the PaymentIntent.

{ "amount": 4600, "amount_capturable": 4600, "amount_received": 0, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 200, "tax": { "total_tax_amount": 400 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 400 }, "line_items": [ { "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } }, { "product_code": "SKU002", "product_name": "Product 002", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "gallons", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } ... }

Capture the PaymentIntent

  • You can add amount_details on the first capture even if they weren’t specified at creation.
  • If you provided amount_details at creation, you must either pass in amount_details or unset them on the first capture.

The same rules apply to amount_details[line_items] – you can add them on the first capture if not specified at creation, but must include or explicitly unset them if they were present at creation.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents/pi_xxxxxxxx/capture \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount_to_capture=2300 \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=100 \ -d "amount_details[tax][total_tax_amount]"=200 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=200 \ -d "amount_details[line_items][0][product_code]"=SKU001 \ -d "amount_details[line_items][0][product_name]"="Product 001" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=feet \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d final_capture=false \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items specified on the first capture.

{ "amount": 4600, "amount_capturable": 2300, "amount_received": 2300, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 100, "tax": { "total_tax_amount": 200 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 200 }, "line_items": { "object": "list", "url": "/v1/payment_intents/pi_xxxxxxxx/amount_details_line_items", "has_more": false, "data": [ { "_id": "li_123", "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } }, "status": "requires_capture" ... }

The PaymentIntent remains in a requires_capture state. At this point, you can either:

  • Continue to capture the PaymentIntent multiple times up to the full amount of the PaymentIntent.
  • Transition the PaymentIntent to a succeeded state by setting final_capture to true, or making a capture without the final_capture parameter (because final_capture defaults to true).
  • If previous captures included amount_details or amount_details[line_items], you must continue to include them in subsequent captures.
  • If previous captures didn’t include these fields, you can’t add them in later captures.
Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents/pi_xxxxxxxx/capture \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount_to_capture=2300 \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=100 \ -d "amount_details[tax][total_tax_amount]"=200 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=200 \ -d "amount_details[line_items][0][product_code]"=SKU002 \ -d "amount_details[line_items][0][product_name]"="Product 002" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=gallons \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d final_capture=false \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items from the first two captures, according to the following rules:

  • discount_amount, tax.total_tax_amount and shipping.amount are summed across captures.
  • shipping.from_postal_code and shipping.to_postal_code might be omitted in the captures, but if it’s provided, you must not change it across captures.
  • line_items will be aggregated across captures.
{ "amount": 4600, "amount_capturable": 0, "amount_received": 4600, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 200, "tax": { "total_tax_amount": 400 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 400 }, "line_items": { "object": "list", "url": "/v1/payment_intents/pi_xxxxxxxx/amount_details_line_items", "has_more": false, "data": [ { "_id": "li_123", "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } }, { "_id": "li_234", "product_code": "SKU002", "product_name": "Product 002", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "gallons", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } }, "status": "succeeded" ... }

Overcapture

You can use payment line items during overcaptures.

Create and confirm an uncaptured PaymentIntent

Note

The API response doesn’t include line items by default. To return line items, expand amount_details.line_items.

Specify the capture_method as manual when creating the PaymentIntent and use the if_available parameter to request overcapture for this payment. The created PaymentIntent allows overcapture if the payment method supports it.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount=4600 \ -d currency=usd \ -d "payment_method_types[0]"=card \ -d payment_method=pm_card_visa \ -d "payment_method_options[card][request_overcapture]"=if_available \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=200 \ -d "amount_details[tax][total_tax_amount]"=400 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=400 \ -d "amount_details[line_items][0][product_code]"=SKU001 \ -d "amount_details[line_items][0][product_name]"="Product 001" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=feet \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d "amount_details[line_items][1][product_code]"=SKU002 \ -d "amount_details[line_items][1][product_name]"="Product 002" \ -d "amount_details[line_items][1][unit_cost]"=2000 \ -d "amount_details[line_items][1][quantity]"=1 \ -d "amount_details[line_items][1][unit_of_measure]"=gallons \ -d "amount_details[line_items][1][payment_method_options][card][commodity_code]"=123123 \ -d confirm=true \ -d capture_method=manual \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items specified on the PaymentIntent.

{ "amount": 4600, "amount_capturable": 4600, "amount_received": 0, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 200, "tax": { "total_tax_amount": 400 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 400 }, "line_items": { "object": "list", "url": "/v1/payment_intents/pi_xxxxxxxx/amount_details_line_items", "has_more": false, "data": [ { "_id": "li_345", "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } }, { "_id": "li_456", "product_code": "SKU002", "product_name": "Product 002", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "gallons", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } } ... }

Capture the PaymentIntent

To capture more than the currently authorised amount on a PaymentIntent, use the capture endpoint and provide an amount_to_capture up to the maximum_amount_capturable.

Pass in an updated amount_details hash that is consistent with the capture amount during Capture.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents/pi_xxxxxxxx/capture \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount_to_capture=5000 \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=200 \ -d "amount_details[tax][total_tax_amount]"=600 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=600 \ -d "amount_details[line_items][0][product_code]"=SKU001 \ -d "amount_details[line_items][0][product_name]"="Product 001" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=feet \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d "amount_details[line_items][1][product_code]"=SKU002 \ -d "amount_details[line_items][1][product_name]"="Product 002" \ -d "amount_details[line_items][1][unit_cost]"=2000 \ -d "amount_details[line_items][1][quantity]"=1 \ -d "amount_details[line_items][1][unit_of_measure]"=gallons \ -d "amount_details[line_items][1][payment_method_options][card][commodity_code]"=123123 \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items specified during capture.

{ "amount": 5000, "amount_capturable": 0, "amount_received": 5000, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 200, "tax": { "total_tax_amount": 600 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 600 }, "line_items": { "object": "list", "url": "/v1/payment_intents/pi_xxxxxxxx/amount_details_line_items", "has_more": false, "data": [ { "_id": "li_567", "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } }, { "_id": "li_678", "product_code": "SKU002", "product_name": "Product 002", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "gallons", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } }, "status": "succeeded" ... }

Incremental authorisation

You can use payment line items during incremental authorisation to authorise additional amounts on a PaymentIntent after the initial authorisation.

Create and confirm an uncaptured PaymentIntent

Note

The API response doesn’t include line items by default. To return line items, expand amount_details.line_items.

Specify the capture_method as manual when creating the PaymentIntent and use the if_available parameter to request incremental authorisation for this payment. The created PaymentIntent allows incremental authorisation if the payment method supports it.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount=4600 \ -d currency=usd \ -d "payment_method_types[0]"=card \ -d payment_method=pm_card_visa \ -d "payment_method_options[card][request_incremental_authorization]"=if_available \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=200 \ -d "amount_details[tax][total_tax_amount]"=400 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=400 \ -d "amount_details[line_items][0][product_code]"=SKU001 \ -d "amount_details[line_items][0][product_name]"="Product 001" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=feet \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d "amount_details[line_items][1][product_code]"=SKU002 \ -d "amount_details[line_items][1][product_name]"="Product 002" \ -d "amount_details[line_items][1][unit_cost]"=2000 \ -d "amount_details[line_items][1][quantity]"=1 \ -d "amount_details[line_items][1][unit_of_measure]"=gallons \ -d "amount_details[line_items][1][payment_method_options][card][commodity_code]"=123123 \ -d confirm=true \ -d capture_method=manual \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items specified on the PaymentIntent.

{ "amount": 4600, "amount_capturable": 4600, "amount_received": 0, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 200, "tax": { "total_tax_amount": 400 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 400 }, "line_items": { "object": "list", "url": "/v1/payment_intents/pi_xxxxxxxx/amount_details_line_items", "has_more": false, "data": [ { "_id": "li_789", "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } }, { "_id": "li_890", "product_code": "SKU002", "product_name": "Product 002", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "gallons", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } } ... }

Increment the authorisation

To authorise additional amounts on a PaymentIntent beyond the initially authorised amount, use the increment_authorisation endpoint and provide an amount up to the maximum incremental authorisation amount supported by the payment method.

Pass in an updated amount_details hash that is consistent with the total authorised amount after the increment.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/payment_intents/pi_xxxxxxxx/increment_authorization \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount=5000 \ -d "payment_details[customer_reference]"=customer_reference \ -d "payment_details[order_reference]"=order_reference \ -d "amount_details[discount_amount]"=200 \ -d "amount_details[tax][total_tax_amount]"=600 \ -d "amount_details[shipping][from_postal_code]"=94110 \ -d "amount_details[shipping][to_postal_code]"=94117 \ -d "amount_details[shipping][amount]"=600 \ -d "amount_details[line_items][0][product_code]"=SKU001 \ -d "amount_details[line_items][0][product_name]"="Product 001" \ -d "amount_details[line_items][0][unit_cost]"=2000 \ -d "amount_details[line_items][0][quantity]"=1 \ -d "amount_details[line_items][0][unit_of_measure]"=feet \ -d "amount_details[line_items][0][payment_method_options][card][commodity_code]"=123123 \ -d "amount_details[line_items][1][product_code]"=SKU002 \ -d "amount_details[line_items][1][product_name]"="Product 002" \ -d "amount_details[line_items][1][unit_cost]"=2000 \ -d "amount_details[line_items][1][quantity]"=1 \ -d "amount_details[line_items][1][unit_of_measure]"=gallons \ -d "amount_details[line_items][1][payment_method_options][card][commodity_code]"=123123 \ -d "expand[0]"="amount_details.line_items"

In the response, the amount_details field contains the line items specified during the increment authorisation and the PaymentIntent’s total authorised amount is updated.

{ "amount": 5000, "amount_capturable": 5000, "amount_received": 0, "payment_details": { "customer_reference": "customer_reference", "order_reference": "order_reference" }, "amount_details": { "discount_amount": 200, "tax": { "total_tax_amount": 600 }, "shipping": { "from_postal_code": "94110", "to_postal_code": "94117", "amount": 600 }, "line_items": { "object": "list", "url": "/v1/payment_intents/pi_xxxxxxxx/amount_details_line_items", "has_more": false, "data": [ { "_id": "li_901", "product_code": "SKU001", "product_name": "Product 001", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "feet", "payment_method_options": { "card": { "commodity_code": "123123" } } }, { "_id": "li_012", "product_code": "SKU002", "product_name": "Product 002", "unit_cost": 2000, "quantity": 1, "unit_of_measure": "gallons", "payment_method_options": { "card": { "commodity_code": "123123" } } } ] } }, "status": "requires_capture" ... }
Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc