Theme switcher

Python

This guide walks you through how to set up and use the zip.tax API in a Python application.


Prerequisites

Before getting started, ensure you have the following:

  1. Basic knowledge of Python.
  2. A Python development environment.
  3. An API key. To subscribe for a new key, please choose a subscription. The guide below uses a Geo level subscription.

1

Configure the Python Environment

For making HTTP requests, we'll use Python's standard requests package. Additionally, we'll use json for parsing JSON responses. These packages should already be available in your Python environment.

2

Start the Python Project

Create a new project directory:

Bash
mkdir ziptax-python && cd ziptax-python
3

The Code

Here is a complete example of a simple Python application that queries the zip.tax API for sales tax information.

Python
import requests import json class Response: def __init__(self, data): metadata = data.get("metadata", {}) response_meta = metadata.get("response", {}) # Backwards-compatible fields self.version = metadata.get("version") self.r_code = response_meta.get("code") # Address detail maps directly from new payload self.address_detail = AddressDetail(data.get("addressDetail", {})) # Build a legacy-style "Result" object from the new v60 structure base_rates = data.get("baseRates", []) tax_summaries = data.get("taxSummaries", []) service = data.get("service", {}) shipping = data.get("shipping", {}) sourcing = data.get("sourcingRules", {}) # Group baseRates by jurType rates_by_type = {} for br in base_rates: jur_type = br.get("jurType") if jur_type: rates_by_type.setdefault(jur_type, []).append(br) def first_rate(jur_type): items = rates_by_type.get(jur_type) or [] return items[0].get("rate") if items else None def first_tax_code(jur_type): items = rates_by_type.get(jur_type) or [] return items[0].get("jurTaxCode") if items else None # Total sales/use rates from taxSummaries sales_rate = None use_rate = None for ts in tax_summaries: if ts.get("taxType") == "SALES_TAX": sales_rate = ts.get("rate") elif ts.get("taxType") == "USE_TAX": use_rate = ts.get("rate") # District-level details district_sales = rates_by_type.get("US_DISTRICT_SALES_TAX") or [] district_use = rates_by_type.get("US_DISTRICT_USE_TAX") or [] result_payload = { # Legacy combined rates "taxSales": sales_rate, "taxUse": use_rate, # Legacy service/freight taxability flags "txbService": service.get("taxable"), "txbFreight": shipping.get("taxable"), # Legacy state/city/county rates "stateSalesTax": first_rate("US_STATE_SALES_TAX"), "stateUseTax": first_rate("US_STATE_USE_TAX"), "citySalesTax": first_rate("US_CITY_SALES_TAX"), "cityUseTax": first_rate("US_CITY_USE_TAX"), "cityTaxCode": first_tax_code("US_CITY_SALES_TAX") or first_tax_code("US_CITY_USE_TAX"), "countySalesTax": first_rate("US_COUNTY_SALES_TAX"), "countyUseTax": first_rate("US_COUNTY_USE_TAX"), "countyTaxCode": first_tax_code("US_COUNTY_SALES_TAX") or first_tax_code("US_COUNTY_USE_TAX"), # Legacy combined district totals "districtSalesTax": sum((br.get("rate") or 0) for br in district_sales) if district_sales else None, "districtUseTax": sum((br.get("rate") or 0) for br in district_use) if district_use else None, # Legacy origin/destination flag "originDestination": sourcing.get("value"), } # Map up to 5 underlying districts to legacy district1..district5 fields for i in range(5): s_br = district_sales[i] if i < len(district_sales) else None u_br = district_use[i] if i < len(district_use) else None idx = i + 1 result_payload[f"district{idx}Code"] = (s_br or u_br or {}).get("jurTaxCode") if (s_br or u_br) else None result_payload[f"district{idx}SalesTax"] = s_br.get("rate") if s_br else None result_payload[f"district{idx}UseTax"] = u_br.get("rate") if u_br else None # Wrap in a list for backwards compatibility self.results = [Result(result_payload)] class Result: def __init__(self, data): self.geo_postal_code = data.get("geoPostalCode") self.geo_city = data.get("geoCity") self.geo_county = data.get("geoCounty") self.geo_state = data.get("geoState") self.tax_sales = data.get("taxSales") self.tax_use = data.get("taxUse") self.txb_service = data.get("txbService") self.txb_freight = data.get("txbFreight") self.state_sales_tax = data.get("stateSalesTax") self.state_use_tax = data.get("stateUseTax") self.city_sales_tax = data.get("citySalesTax") self.city_use_tax = data.get("cityUseTax") self.city_tax_code = data.get("cityTaxCode") self.county_sales_tax = data.get("countySalesTax") self.county_use_tax = data.get("countyUseTax") self.county_tax_code = data.get("countyTaxCode") self.district_sales_tax = data.get("districtSalesTax") self.district_use_tax = data.get("districtUseTax") self.district1_code = data.get("district1Code") self.district1_sales_tax = data.get("district1SalesTax") self.district1_use_tax = data.get("district1UseTax") self.district2_code = data.get("district2Code") self.district2_sales_tax = data.get("district2SalesTax") self.district2_use_tax = data.get("district2UseTax") self.district3_code = data.get("district3Code") self.district3_sales_tax = data.get("district3SalesTax") self.district3_use_tax = data.get("district3UseTax") self.district4_code = data.get("district4Code") self.district4_sales_tax = data.get("district4SalesTax") self.district4_use_tax = data.get("district4UseTax") self.district5_code = data.get("district5Code") self.district5_sales_tax = data.get("district5SalesTax") self.district5_use_tax = data.get("district5UseTax") self.origin_destination = data.get("originDestination") class AddressDetail: def __init__(self, data): self.normalized_address = data.get("normalizedAddress") self.incorporated = data.get("incorporated") self.geo_lat = data.get("geoLat") self.geo_lng = data.get("geoLng") def get_sales_tax(address, api_key): try: # Updated to v60 endpoint api_url = ( f"https://api.zip-tax.com/request/v60" f"?key={api_key}&address={requests.utils.quote(address)}" ) response = requests.get(api_url) if response.status_code != 200: raise Exception(f"Unexpected status code: {response.status_code}") response_data = response.json() return Response(response_data) except Exception as e: print(f"Error fetching sales tax: {e}") return None def main(): api_key = "your_api_key_here" # Replace with your actual API key address = "200 Spectrum Center Dr, Irvine, CA 92618" # Example Address tax_info = get_sales_tax(address, api_key) if tax_info: print(f"Normalized Address: {tax_info.address_detail.normalized_address}") print( f"Address Lat/Lng: " f"{tax_info.address_detail.geo_lat}, {tax_info.address_detail.geo_lng}" ) if tax_info.results and tax_info.results[0].tax_sales is not None: print(f"Rate: {tax_info.results[0].tax_sales * 100:.2f}%") else: print("Rate: N/A") if __name__ == "__main__": main()

Explanation of the Code

  1. API Request: The get_sales_tax function constructs a URL with the API key and an address, makes a GET request, and parses the response.
  2. Response Parsing: The response JSON is unmarshalled for easy access to sales tax details.
  3. Display Results: The main function prints the normalized address, lat/lng, and sales tax rate for the specified address code. You can use any of the response values here to output the data you need.
4

Run the Application

Save the code to a file (e.g., main.py), then run the program:

Bash
python main.py

You should see output similar to this:

Plain text

Conclusion

Integrating the zip.tax API into your Python application is straightforward. By following this guide, you can enhance your application with accurate sales tax information based on address. For more details, refer to the official documentation above at Getting Started.

If you have any questions or feedback, feel free to email us at support@zip.tax. Happy coding!

Was this section helpful?

What made this section unhelpful for you?

On this page
  • Python