How it works
Tax calculated
Provider returns tax amount based on customer location and your tax behavior setting (
exclusive or inclusive).Payment authorized
Payment authorized for the total amount (subtotal + tax for exclusive, or full amount for inclusive).
How tax location is determined
PayNext determines the customer’s tax jurisdiction based on the payment method and available data:| Payment method | Tax location source |
|---|---|
| Apple Pay, Google Pay | Billing address from the wallet |
| All other methods | zip_code and state passed in the customer object |
| Fallback | Cloudflare geolocation from device fingerprint |
zip_code and state in the customer object when creating the checkout session. These two fields are the minimum required for tax calculation—in most cases, the state can be detected automatically from the zip code. For the most accurate calculation, pass the full address object.
If address data is not provided, PayNext uses geolocation data from the customer’s device. Learn more about what data PayNext collects to determine tax location.
Address data and audit risk
The accuracy of your tax location data affects audit risk. When a payment method provides a full billing address (like Apple Pay or Google Pay), PayNext automatically uses it for tax calculation.| Scenario | Approach | Audit risk |
|---|---|---|
| Full billing address | Street-level geocoding | Low |
| Partial address (zip + state) | State-level tax calculation | Low |
| No address provided | Cloudflare geolocation (zip, state, city, coordinates) | Medium |
- Documented methodology — Consistent, defensible process with detailed location data
- Regulatory precedent — Texas PLR guidance confirms IP-based geolocation is acceptable when addresses aren’t collected
- Audit trail — All geolocation data is logged and available for compliance review
Location mismatch handling
When creating a client session with customer country set to US but no address data available (nozip_code/state provided and payment method is not Apple Pay or Google Pay), PayNext falls back to device fingerprint for tax location.
If the fingerprint indicates the customer is outside the US (e.g., Canada), PayNext does not calculate US sales tax for that transaction. The payment processes without tax, and the API returns the “tax doesn’t apply” response structure. This occurs because the customer’s actual location—based on fingerprint data—is outside the tax provider’s supported jurisdiction.
Configuration
Tax configuration follows a hierarchy—set defaults globally and override tax collection at the plan level when needed.Global settings
Configure default tax behavior in Dashboard → Integrations → Tax:| Setting | Description |
|---|---|
| Tax provider | Your connected tax provider (e.g., Numeral) |
| Tax behavior | exclusive (tax added on top) or inclusive (tax included in price) |
| Product category | Product category for tax rate determination—select from the drop-down menu. Each tax provider has its own product categories (e.g., GENERAL_MERCHANDISE, SAAS_GENERAL). Defaults to GENERAL_MERCHANDISE if not set. |
| Tax registrations | Jurisdictions where you’d like to collect tax |
| Collect tax automatically | When enabled, tax is calculated for all payments by default. When disabled, tax is only collected for plans explicitly configured to collect. |
Plan-level settings
Override global tax collection for specific plans in Dashboard → Plans → [Plan Name]. Each plan has acollect_tax setting that controls whether tax is collected for payments under that plan:
collect_tax | Description |
|---|---|
DEFAULT | Uses the global “Collect tax automatically” setting from your tax provider configuration |
COLLECT | Always collect tax for this plan, regardless of the global setting |
DONT_COLLECT | Never collect tax for this plan, regardless of the global setting |
tax object reflects this configuration:
Example plan response
Example plan response
Tax behavior (
exclusive or inclusive) and product category are configured globally on the tax provider, not per plan. All plans that collect tax use the same behavior and product category.Tax in API responses
All payments include atax object. The structure varies based on whether tax was calculated for the transaction.
When tax applies
When tax is enabled for the customer’s location, thetax object includes provider details and calculation status:
Example: Tax calculated ($100 + 7% tax)
Example: Tax calculated ($100 + 7% tax)
When customers pay in other currencies, use
amount_subtotal_usd and amount_tax_usd to see the USD equivalent for reporting.When tax doesn’t apply
When tax is not enabled for the customer’s location (no tax provider configured, location not in your tax registrations, or plan set toDONT_COLLECT), the provider field is null and amount_tax is 0:
Example: Tax not applicable ($100, no tax)
Example: Tax not applicable ($100, no tax)
provider field to determine if tax was calculated:
provideris present → tax was calculated, checkstatusfor the outcomeproviderisnull→ tax not applicable for this transaction
Tax fields
| Field | Description |
|---|---|
provider.id | PayNext internal ID for your tax provider integration |
provider.type | Tax provider type (e.g., NUMERAL) |
calculation_id | Tax provider’s calculation reference |
transaction_id | Tax provider’s transaction reference (populated after settlement) |
amount_subtotal | Revenue amount pre-tax |
amount_subtotal_usd | Revenue amount in USD |
amount_tax | Tax amount collected |
amount_tax_usd | Tax amount in USD |
behavior | exclusive or inclusive |
status | Tax lifecycle status (see below) |
error | Error details when status is failed (see When calculation fails) |
Tax status lifecycle
| Status | Description |
|---|---|
calculated | Tax calculated during authorization, not yet reported to provider |
submitted | Payment settled, tax transaction reported to provider |
reversed | Payment refunded, tax transaction reversed with provider |
failed | Calculation or transaction submission failed (see error for details) |
Amount relationships
| Field | Description |
|---|---|
amount | Total charged to customer |
tax.amount_subtotal | Revenue portion (pre-tax) |
tax.amount_tax | Tax collected |
When calculation fails
If the tax provider doesn’t respond within 1.5 seconds or returns an error, PayNext processes the payment without tax to ensure you don’t lose revenue. Thestatus is failed and an error object contains the failure reason.
Failed transactions appear in Dashboard → Tax → Failed where you can review and submit them manually to your tax provider.
| Error code | Description |
|---|---|
timeout | Tax provider did not respond within 1.5 seconds |
calculation_failed | Tax provider request failed (see message for details) |
| Provider-specific codes | Tax provider error types are mapped directly (e.g., INVALID_CURRENCY_CODE, CALCULATION_NOT_FOUND) |
Example: Timeout error
Example: Timeout error
Example: Provider error
Example: Provider error
Example: Post-capture transaction failure
Example: Post-capture transaction failure
When tax calculation succeeds during authorization but the transaction submission fails after capture, the
status becomes failed while preserving the original calculation amounts:Tax calculation failures are rare. When they occur, absorbing the tax cost is preferable to declining payments and losing revenue.
Webhooks
PayNext sends tax data in thetax object of payment webhook payloads. The tax object is included in:
payment.created— Initial payment with taxstatus: "calculated"(or"failed"if calculation errored)payment.updated— After settlement (status: "submitted"), after refund (status: "reversed"), or after capture failure (status: "failed")refund.created/refund.updated— Taxstatus: "reversed"when refund succeeds
Best practices
Use exclusive pricing for flexibility
Use exclusive pricing for flexibility
Set your global default to
exclusive. This lets you display pre-tax prices and add tax at checkout—the standard approach for US and B2B sales. Override to inclusive only for specific markets (like EU B2C) where tax-inclusive pricing is expected.Start collecting before you register
Start collecting before you register
You can start calculating and collecting tax before you’re officially registered in a jurisdiction. Once registered, most tax providers support backfilling historical transactions. PayNext returns $0 tax for customers in locations where you haven’t enabled tax collection in Integrations.
Use USD amounts for reporting
Use USD amounts for reporting
For reporting convenience, use the
_usd fields (amount_subtotal_usd, amount_tax_usd) to avoid currency conversion complexity. Your final tax liability is available in your tax provider’s dashboard (e.g., Numeral)—use that information for your accounting and filing.