diff --git a/.fern/metadata.json b/.fern/metadata.json
index 7b6e7f1c..b05f0778 100644
--- a/.fern/metadata.json
+++ b/.fern/metadata.json
@@ -13,7 +13,7 @@
"standardwebhooks": ">= 1.0"
}
},
- "originGitCommit": "5e4b7064e04d687363cf69ed2044c705570ebbb7",
+ "originGitCommit": "d9754d1712cd4d25c94baec00749b0109dbe9b7a",
"originGitCommitIsDirty": false,
"invokedBy": "ci",
"requestedVersion": "2.3.0",
diff --git a/.fern/replay.lock b/.fern/replay.lock
index 735e805a..f5f4fe9b 100644
--- a/.fern/replay.lock
+++ b/.fern/replay.lock
@@ -2274,5 +2274,11 @@ generations:
cli_version: unknown
generator_versions:
fernapi/fern-ruby-sdk: 1.28.3
-current_generation: 9a36badc7fc1bfd15a60b2e399c8908fe2ea1aba
+ - commit_sha: 0b0bcb04163574646b910aaf5843df716e31a230
+ tree_hash: 53ee10c0a0610ba54ca3eb23f0182bba1d0808bc
+ timestamp: 2026-10-10T13:30:13.531Z
+ cli_version: unknown
+ generator_versions:
+ fernapi/fern-ruby-sdk: 1.28.3
+current_generation: 0b0bcb04163574646b910aaf5843df716e31a230
patches: []
diff --git a/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request.rb b/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request.rb
index 42e3c3bb..ee36ef99 100644
--- a/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request.rb
+++ b/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request.rb
@@ -8,6 +8,8 @@ class CreatePaymentQuotesRequest < Internal::Types::Model
field :ip_address, -> { String }, optional: true, nullable: false
+ field :presentment_country, -> { String }, optional: true, nullable: false
+
field :presentment_currency, -> { String }, optional: true, nullable: false
field :shipping_address, -> { Whop_sdk::PaymentQuotes::Types::CreatePaymentQuotesRequestShippingAddress }, optional: true, nullable: false
diff --git a/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request_address.rb b/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request_address.rb
index 9437c14e..db5a57ec 100644
--- a/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request_address.rb
+++ b/lib/whop_sdk/payment_quotes/types/create_payment_quotes_request_address.rb
@@ -5,7 +5,7 @@ module PaymentQuotes
module Types
# The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax
# registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country`
- # here, on `shipping_address`, or an `ip_address`; without one the quote is refused with
+ # here, on `shipping_address`, a `presentment_country`, or an `ip_address`; without one the quote is refused with
# `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the
# buyer in the same place, by country, state and postal code, through its own `shipping_address` or its
# confirmation token's billing address, or it is refused with `quote_mismatch`.
diff --git a/lib/whop_sdk/types/payment_quote_located_by.rb b/lib/whop_sdk/types/payment_quote_located_by.rb
index 88c76320..bfdaa10e 100644
--- a/lib/whop_sdk/types/payment_quote_located_by.rb
+++ b/lib/whop_sdk/types/payment_quote_located_by.rb
@@ -7,6 +7,7 @@ module PaymentQuoteLocatedBy
SHIPPING_ADDRESS = "shipping_address"
ADDRESS = "address"
+ PRESENTMENT_COUNTRY = "presentment_country"
IP_ADDRESS = "ip_address"
end
end
diff --git a/lib/whop_sdk/variants/client.rb b/lib/whop_sdk/variants/client.rb
index 55ef661d..0a482c01 100644
--- a/lib/whop_sdk/variants/client.rb
+++ b/lib/whop_sdk/variants/client.rb
@@ -35,6 +35,7 @@ def initialize(client:, base_url: nil, environment: nil)
# @option params [String, nil] :created_after
# @option params [String, nil] :presentment_currency
# @option params [String, nil] :ip_address
+ # @option params [String, nil] :presentment_country
# @option params [Integer, nil] :first
# @option params [String, nil] :after
# @option params [Integer, nil] :last
@@ -47,7 +48,8 @@ def initialize(client:, base_url: nil, environment: nil)
# plan_types: ["renewal"],
# product_ids: ["prod_xxxxxxxxxxxxxx"],
# presentment_currency: "auto",
- # ip_address: "203.0.113.7"
+ # ip_address: "203.0.113.7",
+ # presentment_country: "JP"
# )
#
# @return [Whop_sdk::Variants::Types::ListVariantsResponse]
@@ -65,6 +67,7 @@ def list(request_options: {}, **params)
query_params["created_after"] = params[:created_after] if params.key?(:created_after)
query_params["presentment_currency"] = params[:presentment_currency] if params.key?(:presentment_currency)
query_params["ip_address"] = params[:ip_address] if params.key?(:ip_address)
+ query_params["presentment_country"] = params[:presentment_country] if params.key?(:presentment_country)
query_params["first"] = params[:first] if params.key?(:first)
query_params["after"] = params[:after] if params.key?(:after)
query_params["last"] = params[:last] if params.key?(:last)
@@ -149,12 +152,14 @@ def create(request_options: {}, **params)
# @option params [String] :id
# @option params [String, nil] :presentment_currency
# @option params [String, nil] :ip_address
+ # @option params [String, nil] :presentment_country
#
# @example
# client.variants.retrieve(
# id: "id",
# presentment_currency: "auto",
- # ip_address: "203.0.113.7"
+ # ip_address: "203.0.113.7",
+ # presentment_country: "JP"
# )
#
# @return [Whop_sdk::Types::Variant]
@@ -163,6 +168,7 @@ def retrieve(request_options: {}, **params)
query_params = {}
query_params["presentment_currency"] = params[:presentment_currency] if params.key?(:presentment_currency)
query_params["ip_address"] = params[:ip_address] if params.key?(:ip_address)
+ query_params["presentment_country"] = params[:presentment_country] if params.key?(:presentment_country)
request = Whop_sdk::Internal::JSON::Request.new(
base_url: request_options[:base_url] || @base_url || @environment&.dig(:api),
diff --git a/lib/whop_sdk/variants/types/list_variants_request.rb b/lib/whop_sdk/variants/types/list_variants_request.rb
index 03d41dfe..a48a0d19 100644
--- a/lib/whop_sdk/variants/types/list_variants_request.rb
+++ b/lib/whop_sdk/variants/types/list_variants_request.rb
@@ -26,6 +26,8 @@ class ListVariantsRequest < Internal::Types::Model
field :ip_address, -> { String }, optional: true, nullable: false
+ field :presentment_country, -> { String }, optional: true, nullable: false
+
field :first, -> { Integer }, optional: true, nullable: false
field :after, -> { String }, optional: true, nullable: false
diff --git a/lib/whop_sdk/variants/types/retrieve_variants_request.rb b/lib/whop_sdk/variants/types/retrieve_variants_request.rb
index c69c9526..16608d0c 100644
--- a/lib/whop_sdk/variants/types/retrieve_variants_request.rb
+++ b/lib/whop_sdk/variants/types/retrieve_variants_request.rb
@@ -9,6 +9,8 @@ class RetrieveVariantsRequest < Internal::Types::Model
field :presentment_currency, -> { String }, optional: true, nullable: false
field :ip_address, -> { String }, optional: true, nullable: false
+
+ field :presentment_country, -> { String }, optional: true, nullable: false
end
end
end
diff --git a/reference.md b/reference.md
index acd383a1..8f4f9dd7 100644
--- a/reference.md
+++ b/reference.md
@@ -27247,7 +27247,7 @@ client.payment_quotes.create(account_id: "biz_xxxxxxxxxxxxxx")
-
-**address:** `Whop_sdk::PaymentQuotes::Types::CreatePaymentQuotesRequestAddress` — The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`.
+**address:** `Whop_sdk::PaymentQuotes::Types::CreatePaymentQuotesRequestAddress` — The buyer's billing address. Where tax is calculated when no shipping address is given, and the address a tax registration belongs to. A seller that collects tax on this purchase needs the buyer located by a `country` here, on `shipping_address`, a `presentment_country`, or an `ip_address`; without one the quote is refused with `quote_location_required`. Only the keys you supply are kept. The payment that consumes the quote must put the buyer in the same place, by country, state and postal code, through its own `shipping_address` or its confirmation token's billing address, or it is refused with `quote_mismatch`.
@@ -27255,7 +27255,7 @@ client.payment_quotes.create(account_id: "biz_xxxxxxxxxxxxxx")
-
-**ip_address:** `String` — The buyer's IP address, when your server makes the call on their behalf. Locates the buyer when neither address carries a country. A quote located this way (`located_by` is `ip_address`) is a preview: a payment refuses it with `quote_preview_only`, so quote again with the buyer's address before paying. Also where `presentment_currency` `auto` and `recommended_currencies` find the buyer's local currency.
+**ip_address:** `String` — The buyer's IP address, when your server makes the call on their behalf. Locates the buyer when neither address carries a country and no `presentment_country` is sent. A quote located this way (`located_by` is `ip_address`) is a preview: a payment refuses it with `quote_preview_only`, so quote again with the buyer's address before paying. Also where `presentment_currency` `auto` and `recommended_currencies` find the buyer's local currency, and where a payment method must be able to collect it.
@@ -27263,7 +27263,15 @@ client.payment_quotes.create(account_id: "biz_xxxxxxxxxxxxxx")
-
-**presentment_currency:** `String` — The currency to price and charge the purchase in. Omit it, or send null, to price in the variants' own currency. `auto` prices in the currency of the country Whop places the buyer's `ip_address` in when the purchase can be converted into it and a payment method can collect it, and in the variants' own currency otherwise, including when no `ip_address` is sent or Whop cannot place it in a country. A three-letter ISO 4217 code, such as `eur`, prices in that currency or is refused: with `presentment_currency_unsupported` when the purchase cannot be converted into it (adaptive pricing is off for the variant, the variant is not a one-time purchase, or `plan` describes a variant that does not exist yet), and with `presentment_currency_not_payable` when no payment method can collect it. A converted quote states every amount in this currency at an `exchange_rate` fixed until `expires_at`, and the payment that consumes it is charged in this currency at that rate.
+**presentment_country:** `String` — The country to price the purchase for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. Prices in the currency `auto` would pick for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, and by this country only without one. With no address that carries a country, tax is estimated for this country (`located_by` is `presentment_country`) at the country level, and a quote located this way is a preview a payment refuses with `quote_preview_only`. Send it only once the buyer has chosen a country: without it, an `ip_address` estimates more precisely, such as for a US state. For a country Whop has no currency for, the quote is priced as `auto` for the buyer's `ip_address`, and tax is still estimated for the country.
+
+
+
+
+
+-
+
+**presentment_currency:** `String` — The currency to price and charge the purchase in. Omit it, or send null, to price in the variants' own currency. `auto` prices in the currency of the country Whop places the buyer's `ip_address` in when the purchase can be converted into it and a payment method can collect it, and in the variants' own currency otherwise, including when no `ip_address` is sent or Whop cannot place it in a country. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, prices in that currency or is refused: with `presentment_currency_unsupported` when the purchase cannot be converted into it (adaptive pricing is off for the variant, the variant is not a one-time purchase, or `plan` describes a variant that does not exist yet), and with `presentment_currency_not_payable` when no payment method can collect it. A converted quote states every amount in this currency at an `exchange_rate` fixed until `expires_at`, and the payment that consumes it is charged in this currency at that rate.
@@ -28341,7 +28349,7 @@ client.payments.create(account_id: "biz_xxxxxxxxxxxxxx")
-
-**quote_id:** `String` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address (`located_by` is `ip_address`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged.
+**quote_id:** `String` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address or by the country the buyer chose (`located_by` is `ip_address` or `presentment_country`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address or by the country the buyer chose; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged.
@@ -39593,7 +39601,8 @@ client.variants.list(
plan_types: ["renewal"],
product_ids: ["prod_xxxxxxxxxxxxxx"],
presentment_currency: "auto",
- ip_address: "203.0.113.7"
+ ip_address: "203.0.113.7",
+ presentment_country: "JP"
)
```
@@ -39681,7 +39690,7 @@ client.variants.list(
-
-**presentment_currency:** `String` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate.
+**presentment_currency:** `String` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate.
@@ -39689,7 +39698,15 @@ client.variants.list(
-
-**ip_address:** `String` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency.
+**ip_address:** `String` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency, and where a payment method must be able to collect it.
+
+
+
+
+
+-
+
+**presentment_country:** `String` — The country to state each variant's prices for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. States them in the currency `auto` would for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, else by the request's own IP address. A country Whop has no currency for is ignored, and the prices are stated as `auto` would state them.
@@ -40041,7 +40058,8 @@ Retrieves the details of an existing variant.
client.variants.retrieve(
id: "id",
presentment_currency: "auto",
- ip_address: "203.0.113.7"
+ ip_address: "203.0.113.7",
+ presentment_country: "JP"
)
```
@@ -40065,7 +40083,15 @@ client.variants.retrieve(
-
-**presentment_currency:** `String` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate.
+**presentment_currency:** `String` — The currency to state each variant's prices in. Omit it, or send null, for each variant's own currency. `auto` states them in the currency of the country Whop places the buyer in: by `ip_address` when your server sends one, and by the request's own IP address otherwise. To choose that country instead, send `presentment_country` in place of this. A three-letter ISO 4217 code, such as `eur`, states them in that currency. A variant converts only where a payment quote for it would be priced in that currency, and stays in its own currency otherwise: a renewing variant, one with adaptive pricing off, a currency no payment method can collect, or `auto` for a buyer Whop cannot place in a country. Converted prices are an estimate at the current exchange rate. Nothing is held: the payment quote the buyer pays from fixes the rate.
+
+
+
+
+
+-
+
+**ip_address:** `String` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency, and where a payment method must be able to collect it.
@@ -40073,7 +40099,7 @@ client.variants.retrieve(
-
-**ip_address:** `String` — The buyer's IP address, when your server reads on their behalf. Needs an API key; any other caller is placed by its own request. Where `presentment_currency` `auto` finds the buyer's local currency.
+**presentment_country:** `String` — The country to state each variant's prices for, as an ISO 3166-1 alpha-2 code such as `JP`, when the buyer chose one: a store's country picker. States them in the currency `auto` would for a buyer in that country, so send it instead of `presentment_currency`, never with it. Whether a payment method can collect that currency is still judged where the buyer is: by `ip_address`, else by the request's own IP address. A country Whop has no currency for is ignored, and the prices are stated as `auto` would state them.
@@ -45135,7 +45161,7 @@ client.payments.direct.create(
-
-**quote_id:** `String` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address (`located_by` is `ip_address`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged.
+**quote_id:** `String` — A payment quote from `POST /payment_quotes`, prefixed `pq_`. The payment charges exactly the quote: its purchase (its variants and quantities, or the `plan` it priced), which this body may then omit, its promo code, and its tax, the quote's `tax_amount` rather than a figure calculated now. Omit it, or send null, to have tax calculated when the payment is charged. The quote must belong to `account_id`. A purchase field you omit or send as null takes the quote's value; the buyer's email, the addresses and the payment method are this request's own, never the quote's. Whatever you do send must describe the quoted purchase: the same variants, quantities and promo code. A quote that priced `plan` takes only the same `plan` you sent to `POST /payment_quotes` (or omit the purchase to take the quoted one), never `plan_id` or `line_items`, and a quote that priced variants by id never takes `plan`. Unless the quote located no buyer (`located_by` is null), the address the payment carries (its shipping address, else its billing address) must put the buyer where the quote priced tax, by country, state and postal code; otherwise the payment is refused with 400 before the payment method is used. A quote located by IP address or by the country the buyer chose (`located_by` is `ip_address` or `presentment_country`) is a preview and cannot be paid. A quote is consumed by one payment: a declined payment keeps it and can be retried; a new payment needs a new quote. A quote cannot be charged through PayPal; such a payment is refused before the payment method is used. A quote priced in a `presentment_currency` is charged in that currency at the quote's `exchange_rate`. A payment refused over its quote carries an error `code`. `quote_expired`: the quote has expired; quote again. `quote_tax_unavailable`: the quote could not price tax; quote again, or omit `quote_id`. `quote_preview_only`: the quote was located by IP address or by the country the buyer chose; quote again with the buyer's address. `quote_in_use` (409): another payment holds the quote. `quote_mismatch`: the purchase or the buyer's address is not the one quoted. `quote_rate_expired`: the exchange rate the quote was priced at has moved too far to charge; quote again. `payment_method_currency_unsupported`: the payment method cannot pay in the quote's currency; use another method, or quote again in another currency. `quote_processor_unsupported`: the payment method cannot pay a quote, as with PayPal; use another method, or omit `quote_id` to have tax calculated when the payment is charged.