Payment Quotes

Create Payment Quote

Changed on

Prices a purchase the way a payment for it will be charged, for a buyer located by the shipping address, then the billing address, then the IP address you pass. The body is the PaymentInput a payment takes plus where the buyer is (address, shipping_address, tax_ids, ip_address); a seller that collects no tax on the purchase can be quoted without them. The purchase is priced from exactly what you send: no buyer is looked up, so no stored registration or purchase history applies. Quote what you are about to charge and pass the quote's id as quote_id when you create the payment: it then charges exactly the purchase, promo code and tax shown here. A quote is priced once, in the plans' own currency or the presentment_currency you ask for, and may be consumed by one payment before expires_at.

post/payment_quotes

Request

  • Base URL: https://api.whop.com/api/v1
  • URL: https://api.whop.com/api/v1/payment_quotes
  • Auth: HTTP bearer

Headers

Idempotency-Keystring
Example:d9105228-4a08-46b1-8b91-42fed586d383

A unique key that makes this request safe to retry. See Idempotent requests.

Request body

account_idstring required

The account the purchase belongs to, prefixed biz_.

plan_idstring

The variant purchased, prefixed plan_. It must belong to the account. Mutually exclusive with plan and line_items.

promo_codestring nullable

The promo code as the buyer typed it, matched within the account regardless of case and surrounding spaces, as checkout matches it. It must be valid for the variant. Send it or promo_code_id, not both; an empty or whitespace-only string counts as not sent. A code the account does not have, or one that is no longer active, is refused before anything is written, with the error code promo_invalid. A code this purchase cannot use, such as one with no uses left or one restricted to other variants, products or buyers, is refused with promo_invalid too, and the error's message says why.

promo_code_idstring nullable

An active promo code to apply, prefixed promo_. It must belong to the account and be valid for the variant. Send it or promo_code, not both. A code this purchase cannot use is refused with the error code promo_invalid, and the error's message says why.

ip_addressstring nullable

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.

presentment_currencystring nullable

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.

Example request

{
  "account_id": "biz_xxxxxxxxxxxxxx",
  "line_items": [
    {
      "plan_id": "plan_xxxxxxxxxxxxxx",
      "quantity": 1
    }
  ],
  "plan": {
    "application_fee_amount": 2,
    "currency": "usd",
    "initial_price": 31,
    "override_tax_type": "inclusive",
    "plan_type": "one_time",
    "product": {
      "collect_shipping_address": true,
      "custom_statement_descriptor": "WHOP*INLINE",
      "description": "Quoted, then sent with the payment.",
      "external_identifier": "quoted-again",
      "global_affiliate_status": "enabled",
      "headline": "Product headline",
      "redirect_purchase_url": "https://example.com/thanks",
      "title": "Quoted again",
      "visibility": "visible"
    },
    "product_id": "prod_xxxxxxxxxxxxxx",
    "visibility": "visible"
  },
  "plan_id": "plan_xxxxxxxxxxxxxx",
  "promo_code": "SHINE20",
  "promo_code_id": "promo_xxxxxxxxxxxxxx",
  "address": {
    "city": "Austin",
    "country": "US",
    "line1": "1114 Bouldin Ave",
    "line2": "Unit B",
    "name": "Dana Whitfield",
    "postal_code": "78704",
    "state": "TX"
  },
  "ip_address": "203.0.113.7",
  "presentment_currency": "auto",
  "tax_ids": [
    {
      "type": "eu_vat",
      "value": "DE123456789"
    }
  ]
}

Response

payment quote priced

account_idstring required

The account the purchase is priced for, prefixed biz_.

base_currencystring required

Three-letter ISO 4217 code of the variants' own currency, lowercase. Equal to currency when nothing was converted.

created_atstring required

When the quote was priced, as an ISO 8601 timestamp.

currencystring required

Three-letter ISO 4217 currency code the purchase is priced and charged in, lowercase: the variants' own currency, or the presentment_currency it was converted into.

exchange_ratestring nullable required

How many units of currency one unit of base_currency buys, as a decimal string such as "5.4321": the rate the variants' prices were converted at, fixed until expires_at, and the rate a payment consuming the quote is charged at. A string, like money amounts, so no float rounds it in transit. Null when nothing was converted.

expires_atstring required

When the quote stops being chargeable, as an ISO 8601 timestamp. Quote again after it.

idstring required

Payment quote ID, prefixed pq_.

located_by'shipping_address' | 'address' | 'ip_address' | 'null' nullable required

Which location tax was calculated for: shipping_address when it carries a country, else the billing address when it does, else the buyer's ip_address. A quote located by ip_address is a preview: a payment cannot use it, so quote again with the buyer's address to pay. Null when nothing in the request located the buyer, which only a seller that collects no tax on this purchase is quoted without; tax_status is then not_applicable.

payment_idstring nullable required

The payment holding this quote, prefixed pay_, or null while it is unspent. A declined payment keeps its quote and can be retried; check that payment's status.

promo_code_idstring nullable required

The promo code the quote applied, prefixed promo_, or null.

recommended_currenciesstring[] required
tax_behavior'inclusive' | 'exclusive' | 'null' nullable required

Whether tax is added on top of the price (exclusive) or already inside it (inclusive). Null when no tax was calculated.

tax_status'calculated' | 'not_applicable' | 'unavailable' required

calculated: every line was priced and a payment may consume the quote. not_applicable: this seller collects no tax on this purchase, so the quote owes none and may still be consumed. unavailable: tax could not be priced — the provider did not answer, or this seller's tax setup cannot price a purchase here — so a payment refuses the quote; quote again, or charge without quote_id to have tax calculated at charge time.

Example response

{
  "account_id": "biz_xxxxxxxxxxxxxx",
  "address": {
    "city": "Austin",
    "country": "US",
    "line1": "1114 Bouldin Ave",
    "line2": "Unit B",
    "name": "Dana Whitfield",
    "postal_code": "78704",
    "state": "TX"
  },
  "base_currency": "usd",
  "base_total": {
    "amount": "-1234.56",
    "currency": "usd",
    "decimals": 2,
    "display_decimals": 2
  },
  "created_at": "2026-01-01T12:00:00.000Z",
  "currency": "usd",
  "discount": {
    "amount": "-1234.56",
    "currency": "usd",
    "decimals": 2,
    "display_decimals": 2
  },
  "exchange_rate": "0.918",
  "expires_at": "2026-01-01T12:00:00.000Z",
  "id": "pq_xxxxxxxxxxxxxx",
  "line_items": [
    {
      "discount": {
        "amount": "-1234.56",
        "currency": "usd",
        "decimals": 2,
        "display_decimals": 2
      },
      "plan_id": "plan_xxxxxxxxxxxxxx",
      "quantity": 1,
      "subtotal": {
        "amount": "-1234.56",
        "currency": "usd",
        "decimals": 2,
        "display_decimals": 2
      },
      "tax_amount": {
        "amount": "-1234.56",
        "currency": "usd",
        "decimals": 2,
        "display_decimals": 2
      },
      "total": {
        "amount": "-1234.56",
        "currency": "usd",
        "decimals": 2,
        "display_decimals": 2
      }
    }
  ],
  "located_by": "address",
  "payment_id": "pay_xxxxxxxxxxxxxx",
  "recommended_currencies": [
    "usd"
  ],
  "shipping_address": {
    "city": "Austin",
    "country": "US",
    "line1": "1114 Bouldin Ave",
    "line2": "Unit B",
    "name": "Dana Whitfield",
    "postal_code": "78704",
    "state": "TX"
  },
  "subtotal": {
    "amount": "-1234.56",
    "currency": "usd",
    "decimals": 2,
    "display_decimals": 2
  },
  "tax_amount": {
    "amount": "-1234.56",
    "currency": "usd",
    "decimals": 2,
    "display_decimals": 2
  },
  "tax_behavior": "exclusive",
  "tax_ids": [
    {
      "type": "us_ein",
      "value": "12-3456789"
    }
  ],
  "tax_status": "calculated",
  "total": {
    "amount": "-1234.56",
    "currency": "usd",
    "decimals": 2,
    "display_decimals": 2
  }
}

Changes

    • info

      added the new optional request property /

    • info

      added the required property to the response with the status

    • info

      added the required property to the response with the status

    • info

      added the required property to the response with the status

    • info

      added the required property to the response with the status

    • info

      endpoint added