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:
- Basic knowledge of Python.
- A Python development environment.
- 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:
mkdir ziptax-python && cd ziptax-python3
The Code
Here is a complete example of a simple Python application that queries the zip.tax API for sales tax information.
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
- 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.
- Response Parsing: The response JSON is unmarshalled for easy access to sales tax details.
- 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:
python main.pyYou should see output similar to this:
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!
What made this section unhelpful for you?
On this page
- Python