BagsBags Docs
Guides

Calculate Tax Before Checkout

Use the Tax Quote API to show tax breakdowns before payment.

Bags calculates VAT, GST, and sales tax automatically using regional tax providers routed by customer country (EU VAT, UK VAT, India GST, US sales tax where nexus is active, and zero-tax elsewhere). Request a tax quote before creating a checkout session to show your customers a breakdown of subtotal, tax, and total.


How it works

  1. Customer enters their billing address
  2. You call the tax quote endpoint with the payment link ID and address
  3. Bags returns the tax breakdown (subtotal, tax amount, total) and a signed quoteToken
  4. You pass the quoteToken when creating the checkout session to lock in the tax amount

The quote token is cryptographically signed and ensures the tax amount cannot be tampered with between the quote and checkout steps.


Request a tax quote

const response = await fetch("https://www.getbags.app/api/tax/quote", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BAG_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    paymentLinkId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    customerAddress: {
      address_line_1: "100 Main St",
      address_city: "San Francisco",
      address_province: "CA",
      address_postal_code: "94105",
      address_country: "US",
      address_type: "billing",
    },
  }),
});

const { data: quote } = await response.json();
console.log(`Subtotal: $${(quote.subtotalCents / 100).toFixed(2)}`);
console.log(`Tax:      $${(quote.taxCents / 100).toFixed(2)}`);
console.log(`Total:    $${(quote.totalCents / 100).toFixed(2)}`);
import os
import requests

API_KEY = os.environ["BAG_API_KEY"]
BASE_URL = "https://www.getbags.app"

response = requests.post(
    f"{BASE_URL}/api/tax/quote",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "paymentLinkId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "customerAddress": {
            "address_line_1": "100 Main St",
            "address_city": "San Francisco",
            "address_province": "CA",
            "address_postal_code": "94105",
            "address_country": "US",
            "address_type": "billing",
        },
    },
)

data = response.json()["data"]
print(f"Subtotal: ${data['subtotalCents'] / 100:.2f}")
print(f"Tax:      ${data['taxCents'] / 100:.2f}")
print(f"Total:    ${data['totalCents'] / 100:.2f}")
curl -X POST https://www.getbags.app/api/tax/quote \
  -H "Authorization: Bearer $BAG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "paymentLinkId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "customerAddress": {
      "address_line_1": "100 Main St",
      "address_city": "San Francisco",
      "address_province": "CA",
      "address_postal_code": "94105",
      "address_country": "US",
      "address_type": "billing"
    }
  }'

Response

{
  "status": "success",
  "data": {
    "subtotalCents": 2999,
    "taxCents": 262,
    "totalCents": 3261,
    "calculationId": "calc_abc123",
    "quoteToken": "eyJhbGciOiJIUzI1NiIs..."
  }
}
FieldTypeDescription
subtotalCentsnumberProduct price in cents before tax
taxCentsnumberCalculated tax amount in cents
totalCentsnumberTotal amount including tax in cents
calculationIdstringProvider calculation reference (format varies by region)
quoteTokenstringSigned token to pass to checkout session creation

Using the quote in checkout

Pass the quoteToken and totals snapshot when creating a checkout session via POST /api/checkout/session:

const response = await fetch("https://www.getbags.app/api/checkout/session", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    linkId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    quoteToken: quote.quoteToken,
    walletAddress: "0xCustomerWallet",
    walletType: "evm",
    network: "base",
    customer: {
      name: "Jane Doe",
      email: "jane@example.com",
      address: "100 Main St, San Francisco, CA 94105",
      country: "US",
    },
    totalsSnapshot: {
      subtotalCents: quote.subtotalCents,
      taxCents: quote.taxCents,
      totalCents: quote.totalCents,
      calculationId: quote.calculationId,
    },
  }),
});

Address fields

FieldTypeRequiredDescription
address_line_1stringYesStreet address
address_citystringYesCity
address_provincestringYesState, province, or region code
address_postal_codestringYesZIP or postal code
address_countrystringYesISO 3166-1 alpha-2 country code (e.g., US, DE, GB)
address_typestringYesMust be "billing"

Tax calculation details

Bags routes quotes to the active provider for the customer's country:

RegionProvider (v0)
EUHardcoded EU VAT rates (per active country gate)
GBUK VAT
INIndia GST
USUS sales tax (per active nexus state; $0 when no nexus)
OtherZero tax

Tax is based on the customer's billing address and Bags' MoR registration. Coverage expands as new regions activate — do not assume every jurisdiction returns non-zero tax. See Tax Collection & Filing for remittance.


What's next

On this page