Skip to main content

salestax-python

PyPI Python versions CI License: MIT

Official Python SDK for the Sales Tax Calculator API — immutable sales tax calculations, transactions, adjustments, batches, and coverage checks.

Zero runtime dependencies for the sync client. Full type hints.

Install

pip install salestax-python

Async support:

pip install salestax-python[async]

Quickstart

from salestax import SalesTaxClient

with SalesTaxClient() as client:  # reads SALESTAX_API_KEY
    calc = client.calculations.create(
        currency="CAD",
        tax_behavior="exclusive",
        billing_event="subscription_start",
        seller={
            "country": "CA",
            "channel_role": "direct_legal_supplier",
            "registrations": [
                {"country": "CA", "state": "ON", "type": "gst_hst", "effective_from": "2026-01-01"},
            ],
        },
        customer={
            "type": "consumer",
            "address": {"country": "CA", "state": "ON", "postal_code": "M5V 2T6"},
        },
        lines=[
            {"reference": "subscription", "amount": "100.00", "quantity": "1", "tax_code": "saas"},
        ],
        idempotency_key="order-1001-abc12345",
    )

print(calc["outcome"])  # 'calculated'
print(calc["tax"])      # '13.00'
print(calc["total"])    # '113.00'

Get your API key at salestaxcalculatorapi.com

Resources

Resource Methods
client.calculations create, get, create_batch, get_batch
client.transactions create, get
client.transactions.adjustments create, list, get
client.batches get
client.coverage check

Transactions

Finalize a calculation as an immutable commercial record:

txn = client.transactions.create(
    calculation_id=calc["id"],
    reference="order-1001",
    idempotency_key="order-1001-txn-001",
)
print(txn["adjusted_amount"], txn["adjusted_tax"])

Adjustments

Reverse part of a transaction by exact amount or proportional quantity:

adj = client.transactions.adjustments.create(
    txn["id"],
    reference="refund-order-1001",
    reason="refund",
    lines=[{"line_id": "line_01J6...", "amount": "25.00"}],
    idempotency_key="refund-order-1001-001",
)
print(adj["tax"])

Batches

Process up to 100 calculations asynchronously:

batch = client.calculations.create_batch(
    [calc_a, calc_b, calc_c],
    reference="batch-2026-09-23",
    idempotency_key="batch-2026-09-23-xyz",
)

status = client.batches.get(batch["id"])
for item in status.get("items", []):
    print(item["index"], item["status"])

Coverage

Check qualification before you calculate:

coverage = client.coverage.check(
    country="CA",
    state="ON",
    tax_code="saas",
    transaction_type="sale",
)
print(coverage["qualification"])  # 'qualified' | 'review_required' | 'unsupported'

Async

import asyncio
from salestax import AsyncSalesTaxClient

async def main():
    async with AsyncSalesTaxClient() as client:
        calc = await client.calculations.create(
            currency="CAD",
            tax_behavior="exclusive",
            billing_event="subscription_start",
            seller={
                "country": "CA",
                "channel_role": "direct_legal_supplier",
                "registrations": [
                    {"country": "CA", "state": "ON", "type": "gst_hst",
                     "effective_from": "2026-01-01"},
                ],
            },
            customer={
                "type": "consumer",
                "address": {"country": "CA", "state": "ON", "postal_code": "M5V 2T6"},
            },
            lines=[{"reference": "sub", "amount": "100.00", "tax_code": "saas"}],
            idempotency_key="order-1001-abc12345",
        )
        print(calc["tax"])

asyncio.run(main())

Audit expansion

Request the customer-safe audit expansion on any calculable resource:

calc = client.calculations.create(
    # ...same params as above...
    expand="audit",
)
print(calc.get("audit", {}).get("components"))

Error Handling

Every status code maps to a typed error class. Field-level errors carry a JSON Pointer in err.param.

from salestax import RateLimitError, SalesTaxError, ValidationError

try:
    client.calculations.create(...)
except RateLimitError as err:
    # err.retry_after_ms - back off
    # err.request_id
    ...
except ValidationError as err:
    # err.param - JSON Pointer to the offending field, e.g. '/lines/0/amount'
    ...
except SalesTaxError as err:
    # err.code, err.request_id, err.retryable, err.status_code
    ...

Idempotency

Every mutating request accepts an Idempotency-Key. Reuse the same key when retrying the same operation. The key must be 8-255 characters matching [A-Za-z0-9][A-Za-z0-9._:-]{7,254}.

client.calculations.create(..., idempotency_key="order-1001-abc12345")

Reusing a key with a different request body returns 409 idempotency_conflict.

Configuration

from salestax import RetryPolicy, SalesTaxClient

client = SalesTaxClient(
    api_key="stca_...",
    timeout_ms=20_000,
    retry=RetryPolicy(
        max_retries=4,
        initial_delay_ms=250,
        max_delay_ms=8_000,
        backoff_factor=2.0,
        jitter=True,
    ),
)

Defaults

Option Default
base_url https://api.salestaxcalculatorapi.com
timeout_ms 30000
retry.max_retries 2
retry.initial_delay_ms 250
retry.max_delay_ms 8000
retry.backoff_factor 2.0
retry.jitter True

Behavior

  • Retries — 5xx, network failures, and 429 responses are retried automatically with exponential backoff and full jitter. Retry-After and retry_after_seconds are honored when present. 4xx responses other than 429 are returned to the caller unchanged.
  • Timeouts — each request is aborted after timeout_ms and surfaced as a TimeoutError.
  • Hooks — throwing inside a hook never breaks the request flow. The exception is swallowed and the SDK continues.
  • Money and quantity — always decimal strings matching the OpenAPI Money and Quantity patterns. amount is the total for the line, not a per-unit price.
  • Unknown fields — the API rejects unknown JSON fields. The SDK passes the request body through unchanged so server-side validation is authoritative.

Also Available For

Documentation

Full API reference at salestaxcalculatorapi.com/docs

License

MIT (c) InstaBlick USA

Metadata

Release files for salestax-python 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for salestax-python 0.2.0
File Size Uploaded
salestax_python-0.2.0.tar.gz 26.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for salestax-python 0.2.0
File Interpreter ABI Platform
salestax_python-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 50.4 kB

Release files / salestax_python-0.2.0.tar.gz

Download URL salestax_python-0.2.0.tar.gz
Size 26.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8ad30601222714bbacdc7b2ef1cf068d1f044046070c49dce6bc8fac5c8358b8
BLAKE2b-256 checksum
How to use checksums
12b87748527679a7cbacf4bd598ac9d5642c8f7c13323c212f279dc7b4af1711
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release files / salestax_python-0.2.0-py3-none-any.whl

Download URL salestax_python-0.2.0-py3-none-any.whl
Size 23.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5ffba5dec6aebfe2691601a0d802899d8ee8aa3c18419789754cff7c74251d22
BLAKE2b-256 checksum
How to use checksums
24517e63e299fbc05d6da5a34dc8699e60f026b30ae43870f64df73b28e3803a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page