Bag is live — accept USDC & card payments globally. Get started →
BagBag Docs
Guides

Calculate Tax Before Checkout

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

Calculate Tax Before Checkout

Bag calculates VAT, GST, and sales tax automatically using Numeral. 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. Bag 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

import { Bag } from "@tbagtapp/sdk";

const bag = new Bag({ apiKey: process.env.BAG_API_KEY! });

const quote = await bag.checkout.getTaxQuote({
  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",
  },
});

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://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://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
calculationIdstringNumeral calculation reference
quoteTokenstringSigned token to pass to checkout session creation

Using the quote in checkout

Pass the quoteToken and totals snapshot when creating a checkout session:

const session = await bag.checkout.createSession({
  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

Bag uses Numeral for tax calculation. The engine handles:

  • US sales tax — State, county, and city-level rates
  • EU VAT — Per-country rates with reverse charge for B2B
  • UK VAT — Standard and reduced rates
  • Canadian GST/HST/PST — Federal and provincial taxes
  • Australian GST — Goods and services tax
  • Other jurisdictions — Expanding coverage

Tax is calculated based on the customer's billing address and the merchant's tax registration status. See Tax Collection & Filing for details on how Bag handles remittance.


What's next

On this page