Explainer · US Sales Tax Rates API

How sales tax rates by address work

A sales tax rate for an address is the sum of the rates of every jurisdiction that taxes that location: the state, and where they levy one, the county, the city and special districts. In the Streamlined Sales Tax (SST) member states, each state publishes a boundary file that says which jurisdictions apply to an address range, ZIP+4 or 5-digit ZIP, and a rate file with each jurisdiction's rates and effective dates. You look the address up in the most precise boundary records available, falling back from address to ZIP+4 to 5-digit ZIP, and add up the rates in force on the date of the sale. That gives the published rate, not the tax due on a sale.

By New Odyssey · Published · Markdown

The SST rate and boundary files

The Streamlined Sales and Use Tax Agreement is an agreement among states to simplify sales tax administration. Its member states post their data on the Streamlined Sales Tax Governing Board's site. As the Board puts it: "Each Streamlined Member State is required to provide a rate file and a boundary file. The boundary file generally identifies the tax codes (for each taxing jurisdiction) that apply to an address based on either the 5 or 9-digit zip code. However, for some states the tax codes are based on the actual address. The rate file provides the rates that apply to each tax code."

What each file holds
FileWhat a record holds
Boundary fileAn address range (street, house number range and odd/even side), a ZIP+4 range or a 5-digit ZIP, the jurisdiction codes that apply to it (state, county, place, special districts) and its effective dates
Rate fileOne jurisdiction code with its general and food/drug rates, each for intrastate and interstate sales, and the dates the rate applies

"Files are updated quarterly and are to be posted to this website by the first day of the month prior to the beginning of each calendar quarter. States are only required to post a new file if changes were made." Under the Agreement, local rate changes take effect only on the first day of a calendar quarter, after at least sixty days' notice to sellers.

From an address to a rate

The Agreement sets the order a seller uses: an address-based record when the state publishes one, then the ZIP+4 record, then the 5-digit ZIP. Address-based records are optional for states, so in some states the most precise answer is a ZIP+4.

  1. Address range. Normalise the street line (house number, directionals, street name, suffix) and find the boundary record whose range contains the house number, on the right side of the street.
  2. ZIP+4. If no address range matches, use the record for the 9-digit ZIP. When a ZIP+4 area contains more than one rate, the Agreement requires the state to assign the lowest combined rate in that area.
  3. 5-digit ZIP. If there is no usable ZIP+4, use the 5-digit ZIP record. For a 5-digit area with more than one rate, the state may assign the highest, the lowest or a blended rate.
  4. Rates on the date. For each jurisdiction code in the chosen record, take the rate in force on the date of the sale and add them up.

ZIP codes are mail routes, not tax boundaries. One 5-digit ZIP often spans several cities or districts, which is why a ZIP-level answer can be wrong for a particular address and why the address lookup comes first.

How the Olympus API does it

The US Sales Tax Rates API loads each published state's SST files and follows the same order. Every lookup answers 200 with a status:

Lookup results
statusMeaning
matchedExactly one set of jurisdictions applies and each has one published rate; combined_rates is set
ambiguousThe address or ZIP maps to more than one set of jurisdictions (common for 5-digit ZIPs); every candidate is returned with its own rates and no single rate is chosen
unmatchedNothing in the state's files matches, or a jurisdiction's rate is missing for the date
unsupportedThe state is not published, or the date is outside the published range
  • match.method says which records answered (address_range, zip4 or zip5), match.confidence how specific the answer is, and match.attempted which methods were tried. A fallback_used notice says when an address was answered from ZIP records.
  • candidates[].sst_default marks the jurisdiction set the state assigns to the ZIP+4 or 5-digit record. It is the state's default for the area, not necessarily the rate at a given address.
  • Rates are exact decimal fractions (0.0725 is 7.25%), as the state publishes them; food/drug rates are null where a state leaves them blank.
  • Every jurisdiction rate and boundary record carries provenance, including the SST file it came from (source_version is the file name).

Example: an address in Lincoln, Nebraska

Rates for a street address
curl -s -G "https://api.olympus.new-odyssey.com/v1/sales-tax/rates/address" \
  --data-urlencode "street=1445 K St" \
  --data-urlencode "city=Lincoln" \
  --data-urlencode "state=NE" \
  --data-urlencode "zip=68508" \
  -H "X-API-Key: $OLYMPUS_API_KEY"
Rates for a ZIP+4, or every candidate for a 5-digit ZIP
curl -s "https://api.olympus.new-odyssey.com/v1/sales-tax/rates/zip/68508?state=NE" \
  -H "X-API-Key: $OLYMPUS_API_KEY"
Response shape (values elided)
{
  "data": {
    "status": "matched",
    "reason": null,
    "date": "2026-10-21",
    "normalized": { "house_number": "1445", "street_name": "…", "suffix": "…", "state": "NE", "zip5": "68508", … },
    "state": { "code": "NE", "name": "Nebraska", "status": "published" },
    "match": { "method": "address_range | zip4 | zip5", "confidence": "high | medium | low", "attempted": [ … ] },
    "combined_rates": { "general_intrastate": …, "general_interstate": …, "food_drug_intrastate": …, "food_drug_interstate": … },
    "candidates": [{
      "complete": true,
      "jurisdictions": [
        { "level": "state", "code": "31", "rates": { … }, "effective_from": "…", "effective_to": null, "provenance": { … } },
        { "level": "city", "code": "…", "fips": "…", "rates": { … }, "provenance": { … } }
      ],
      "boundary": { "record_type": "A | 4 | Z", "provenance": { … } }
    }]
  },
  "meta": {
    "notices": [
      { "code": "not_a_taxability_determination", "message": "…" },
      { "code": "source_not_certified", "message": "…" }
    ]
  }
}

In Python, handle every status, not only matched:

sales_tax.py
import os
import requests

API = "https://api.olympus.new-odyssey.com"
HEADERS = {"X-API-Key": os.environ["OLYMPUS_API_KEY"]}

r = requests.get(
    f"{API}/v1/sales-tax/rates/address",
    params={"street": "1445 K St", "city": "Lincoln", "state": "NE", "zip": "68508"},
    headers=HEADERS,
    timeout=30,
)
r.raise_for_status()
result = r.json()["data"]

if result["status"] == "matched":
    print("method:", result["match"]["method"], "confidence:", result["match"]["confidence"])
    print("combined general rate:", result["combined_rates"]["general_intrastate"])
    for j in result["candidates"][0]["jurisdictions"]:
        print(" ", j["level"], j["code"], j["rates"]["general_intrastate"] if j["rates"] else None, j["effective_from"])
elif result["status"] == "ambiguous":
    # Several jurisdiction sets apply; no single rate is chosen for you.
    for c in result["candidates"]:
        print("candidate:", c["combined_rates"], "sst_default:", c["sst_default"])
else:
    print(result["status"], result["reason"])  # unmatched or unsupported

for n in r.json()["meta"]["notices"]:
    print("notice:", n["code"])

From an AI agent, the lookup_us_sales_tax MCP tool takes an address (street, state and zip or city) or a zip, plus an optional date, and returns the same result with its notices.

Effective dates

  • Rates and boundary records carry effective dates. Pass date=YYYY-MM-DD to look up another day; the default is today in America/New_York.
  • Because states post a quarter's files about a month before it starts, rates for the next quarter are often available ahead of time.
  • Each state is served for the dates its files cover (dates_from to dates_to in GET /v1/sales-tax/coverage). A date outside that range is unsupported, so a quarter a state has not posted is never answered from older files.

Why a rate is not the tax due

A published rate is one input to a tax calculation. What a seller actually owes also depends on rules the rate files don't contain:

  • Taxability: whether the item is taxable at all, or at a reduced rate (food, clothing, software and services are treated differently by different states).
  • Sourcing: which location's rate applies, for example the seller's location or the buyer's delivery address, which depends on the state and the type of sale.
  • Nexus: whether the seller has to collect tax in that state at all.
  • Exemptions and holidays: exempt buyers, exemption certificates and sales tax holidays.
  • Other taxes: lodging, excise and other special taxes are not in the SST rate files.

Every response repeats this in meta.notices (not_a_taxability_determination). The API does not calculate tax on a transaction. For that, sellers in SST states can use a Certified Service Provider (CSP), which the SST describes as "an agent certified under the Streamlined Sales and Use Tax Agreement to perform all the seller's sales and use tax functions, other than the seller's obligation to remit tax on its own purchases."

Which states we cover

The Streamlined Sales Tax Governing Board lists 23 full member states and one associate member, Tennessee. As of 2026-10-21 the API publishes 17 of them:

Published states
PublishedNotes
IN, KY, MI, NJ, RISingle-rate states: every ZIP maps to the state rate. New Jersey's Urban Enterprise Zone and Salem County reduced rates apply only to qualified sellers and are not applied
MN, ND, UT, WVZIP-level boundaries only, so street addresses match at ZIP+4 or 5-digit ZIP; responses carry a notice
NEGood Life District rates are not applied; affected responses carry a notice
NV, OK, SD, TN, VT, WI, WYMatching uses the record types each state's files contain (match_methods in coverage). Wisconsin's files truncate street names to 20 characters; affected responses carry a notice

GET /v1/sales-tax/coverage is the authoritative list, with each state's files and dates. Every other state, including non-members such as California, Texas, New York and Florida, answers unsupported, with no rate.

Not certified by SST. Data from the Streamlined Sales Tax Governing Board rate and boundary files, as posted by each member state. The Streamlined Sales Tax Governing Board does not certify Olympus or its use of the data, and Olympus is not a Certified Service Provider. Every response says so in meta.notices (source_not_certified).

Sources