Skip to main content

Official Python SDK for the Ziptax API

Project description

Ziptax Python SDK

Official Python SDK for the Ziptax API - Get accurate sales and use tax rates for any US or Canadian address.

Python Version License

Features

  • 🚀 Simple and intuitive API
  • 🔄 Automatic retry logic with exponential backoff
  • ✅ Input validation
  • 🔍 Type hints for better IDE support
  • 📦 Pydantic models for response validation
  • 🔒 Comprehensive error handling
  • ⚡ Support for concurrent operations
  • 🧪 Well-tested with high code coverage

Installation

pip install ziptax-sdk

Quick Start

from ziptax import ZiptaxClient

# Initialize the client with your API key
client = ZiptaxClient.api_key("your-api-key-here")

# Get sales tax by address
response = client.request.GetSalesTaxByAddress(
    "200 Spectrum Center Drive, Irvine, CA 92618"
)

print(f"Address: {response.addressDetail.normalizedAddress}")
if response.tax_summaries:
    for summary in response.tax_summaries:
        print(f"{summary.summary_name}: {summary.rate * 100:.2f}%")

# Always close the client when done
client.close()

Usage

Initialize the Client

from ziptax import ZiptaxClient

# Basic initialization
client = ZiptaxClient.api_key("your-api-key-here")

# With custom configuration
client = ZiptaxClient.api_key(
    "your-api-key-here",
    timeout=60,           # Request timeout in seconds
    max_retries=5,        # Maximum retry attempts
    retry_delay=2.0,      # Base delay between retries
)

# Using as a context manager (recommended)
with ZiptaxClient.api_key("your-api-key-here") as client:
    response = client.request.GetSalesTaxByAddress("123 Main St")

Get Sales Tax by Address

response = client.request.GetSalesTaxByAddress(
    address="200 Spectrum Center Drive, Irvine, CA 92618",
    country_code="USA",      # Optional: "USA" or "CAN" (default: "USA")
    historical="2024-01",    # Optional: Historical date (YYYY-MM format)
    format="json",           # Optional: "json" or "xml" (default: "json")
)

# Access response data
print(response.addressDetail.normalizedAddress)
print(response.addressDetail.geoLat)
print(response.addressDetail.geoLng)

# Response code
print(f"Response: {response.metadata.response.code} - {response.metadata.response.message}")

# Tax summaries with display rates
if response.tax_summaries:
    for summary in response.tax_summaries:
        print(f"{summary.summary_name}: {summary.rate}")
        for display_rate in summary.display_rates:
            print(f"  {display_rate.name}: {display_rate.rate}")

# Base rates by jurisdiction
if response.base_rates:
    for rate in response.base_rates:
        print(f"{rate.jur_name} ({rate.jur_type}): {rate.rate}")

# Sourcing rules
if response.sourcing_rules:
    print(f"Sourcing: {response.sourcing_rules.value}")

Get Sales Tax by Geolocation

response = client.request.GetSalesTaxByGeoLocation(
    lat="33.6489",
    lng="-117.8386",
    country_code="USA",
    format="json",
)

print(response.addressDetail.normalizedAddress)

Get Account Metrics

metrics = client.request.GetAccountMetrics()

print(f"Core Requests: {metrics.core_request_count:,} / {metrics.core_request_limit:,}")
print(f"Core Usage: {metrics.core_usage_percent:.2f}%")
print(f"Geo Requests: {metrics.geo_request_count:,} / {metrics.geo_request_limit:,}")
print(f"Geo Usage: {metrics.geo_usage_percent:.2f}%")
print(f"Account Active: {metrics.is_active}")

Configuration

You can configure the client using dict-style access:

client = ZiptaxClient.api_key("your-api-key-here")

# Set configuration options
client.config["format"] = "json"
client.config["timeout"] = 60

# Get configuration options
timeout = client.config["timeout"]

Error Handling

The SDK provides comprehensive error handling with specific exception types:

from ziptax import (
    ZipTaxClient,
    ZipTaxValidationError,
    ZipTaxAuthenticationError,
    ZipTaxRateLimitError,
    ZipTaxServerError,
    ZipTaxError,
)

client = ZipTaxClient.api_key("your-api-key-here")

try:
    response = client.request.GetSalesTaxByAddress("123 Main St")

except ZipTaxValidationError as e:
    # Input validation errors
    print(f"Validation error: {e.message}")

except ZipTaxAuthenticationError as e:
    # Authentication failures (401)
    print(f"Authentication error: {e.message}")

except ZipTaxRateLimitError as e:
    # Rate limit exceeded (429)
    print(f"Rate limit error: {e.message}")
    if e.retry_after:
        print(f"Retry after {e.retry_after} seconds")

except ZipTaxServerError as e:
    # Server errors (5xx)
    print(f"Server error: {e.message}")

except ZipTaxError as e:
    # General Ziptax errors
    print(f"Ziptax error: {e.message}")

Exception Hierarchy

ZipTaxError
├── ZipTaxAPIError
│   ├── ZipTaxAuthenticationError (401)
│   ├── ZipTaxAuthorizationError (403)
│   ├── ZipTaxNotFoundError (404)
│   ├── ZipTaxRateLimitError (429)
│   └── ZipTaxServerError (5xx)
├── ZipTaxValidationError
├── ZipTaxConnectionError
├── ZipTaxTimeoutError
└── ZipTaxRetryError

Async Operations

For concurrent operations, you can use asyncio with the SDK:

import asyncio
from concurrent.futures import ThreadPoolExecutor
from ziptax import ZipTaxClient

async def get_tax_rates_async(client, addresses):
    loop = asyncio.get_event_loop()
    with ThreadPoolExecutor() as executor:
        tasks = [
            loop.run_in_executor(
                executor,
                client.request.GetSalesTaxByAddress,
                address
            )
            for address in addresses
        ]
        return await asyncio.gather(*tasks)

# Usage
client = ZipTaxClient.api_key("your-api-key-here")
addresses = ["123 Main St, CA", "456 Oak Ave, NY"]
responses = asyncio.run(get_tax_rates_async(client, addresses))

See examples/async_usage.py for more examples.

Response Models

All API responses are validated using Pydantic models:

V60Response

class V60Response:
    metadata: V60Metadata                           # Response metadata with code/message
    base_rates: Optional[List[V60BaseRate]]        # Tax rates by jurisdiction
    service: V60Service                             # Service taxability
    shipping: V60Shipping                           # Shipping taxability
    sourcing_rules: Optional[V60SourcingRules]     # Origin/Destination rules
    tax_summaries: Optional[List[V60TaxSummary]]   # Tax summaries with display rates
    addressDetail: V60AddressDetail                 # Address details

V60Metadata

class V60Metadata:
    version: str                    # API version (e.g., "v60")
    response: V60ResponseInfo       # Response info object

class V60ResponseInfo:
    code: int                       # Response code (100 = success)
    name: str                       # Response code name
    message: str                    # Response message
    definition: str                 # Schema definition URL

V60TaxSummary

class V60TaxSummary:
    rate: float                                    # Summary tax rate
    tax_type: str                                  # Tax type (e.g., "SALES_TAX")
    summary_name: str                              # Summary description
    display_rates: List[V60DisplayRate]           # Display rates breakdown

class V60DisplayRate:
    name: str                                      # Display rate name
    rate: float                                    # Display rate value

V60AccountMetrics

class V60AccountMetrics:
    core_request_count: int
    core_request_limit: int
    core_usage_percent: float
    geo_enabled: bool
    geo_request_count: int
    geo_request_limit: int
    geo_usage_percent: float
    is_active: bool
    message: str

See the models documentation for complete model definitions.

Development

Setup

# Clone the repository
git clone https://github.com/ziptax/ziptax-python.git
cd ziptax-python

# Install dependencies
pip install -e ".[dev]"

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=src/ziptax --cov-report=html

# Run specific test file
pytest tests/test_client.py

Code Quality

# Format code
black src/ tests/

# Lint code
ruff src/ tests/

# Type checking
mypy src/

Examples

See the examples/ directory for complete examples:

API Reference

ZipTaxClient

Main client for interacting with the Ziptax API.

Methods

  • api_key(api_key, **kwargs) - Create a client instance with an API key
  • close() - Close the HTTP client session

Properties

  • config - Configuration object (dict-like access)
  • request - Functions object for making API requests

Functions

API endpoint functions accessible via client.request.

Methods

  • GetSalesTaxByAddress(address, **kwargs) - Get tax rates by address
  • GetSalesTaxByGeoLocation(lat, lng, **kwargs) - Get tax rates by coordinates
  • GetAccountMetrics(**kwargs) - Get account usage metrics

Requirements

  • Python 3.8+
  • requests >= 2.28.0
  • pydantic >= 2.0.0

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Changelog

See CHANGELOG.md for version history and changes.


Made with ❤️ by the Ziptax Team

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ziptax_sdk-0.1.0b0.tar.gz (22.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ziptax_sdk-0.1.0b0-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file ziptax_sdk-0.1.0b0.tar.gz.

File metadata

  • Download URL: ziptax_sdk-0.1.0b0.tar.gz
  • Upload date:
  • Size: 22.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ziptax_sdk-0.1.0b0.tar.gz
Algorithm Hash digest
SHA256 d6c9f668c3add7c58459b13aa4d73213e4e5e226a91a631ac9c7860cbe3280c5
MD5 3c3c6a5d6764ebcca085b84f4f69a5b4
BLAKE2b-256 c8d219aa077c17cc44a5252865a49cbfbdc29dbc933b12998def90bb60f42ada

See more details on using hashes here.

Provenance

The following attestation bundles were made for ziptax_sdk-0.1.0b0.tar.gz:

Publisher: publish.yml on ZipTax/ziptax-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ziptax_sdk-0.1.0b0-py3-none-any.whl.

File metadata

  • Download URL: ziptax_sdk-0.1.0b0-py3-none-any.whl
  • Upload date:
  • Size: 18.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ziptax_sdk-0.1.0b0-py3-none-any.whl
Algorithm Hash digest
SHA256 3e88fab78d9f3d90f98a9990fe6424f382fdc3412f6873da03871bfbd1ad48db
MD5 c925acbbf65883c78ed73fb85316d915
BLAKE2b-256 827bdd92a298c66ab1de7ff26b731839807c74be62a77760138d3edadc6b9c9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ziptax_sdk-0.1.0b0-py3-none-any.whl:

Publisher: publish.yml on ZipTax/ziptax-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page