API reference · v1.0.0

US Sales Tax Rates API

Download OpenAPI (sales-tax.yaml) · Base URL https://api.olympus.new-odyssey.com

Published sales and use tax rates by jurisdiction, looked up by street address or ZIP code, with the breakdown into state, county, city and special district rates, their effective dates and where each value came from. Served by the Olympus Go gateway.

Not a tax calculation. A rate here is the rate a jurisdiction publishes. It is not the tax due on a transaction and not a taxability determination: whether an item is taxable, which location's rate applies (sourcing), whether the seller must collect at all (nexus) and exemptions all change what is owed. Every response repeats this in meta.notices (not_a_taxability_determination). Transaction tax calculation is not offered.

Coverage. Only the Streamlined Sales Tax (SST) member states listed as published by GET /v1/sales-tax/coverage, for the dates listed there. Every other state (for example California, Texas, New York, Florida) is reported as unsupported, with no rate.

Source. The SST rate and boundary files each member state posts at streamlinedsalestax.org (layout: SST Technology Guide, chapter 5). Rates are as the state publishes them; nothing is estimated. Files are checked twice a month; states post changes quarterly, by the first day of the month before the quarter, so rates for the next quarter are often available ahead of time.

Dates. Rates and boundaries carry effective dates. Pass date (YYYY-MM-DD) to look up another day; the default is today in America/New_York. Each state has its own dates_from..dates_to (coverage); dates outside it are unsupported, so a quarter a state has not posted yet is never answered from its older files.

Results. Lookups always answer 200 with a status:

  • matched: exactly one set of jurisdictions applies and every jurisdiction has one published rate. combined_rates is set.
  • ambiguous: the address or ZIP maps to more than one set of jurisdictions (common for 5-digit ZIPs). Every candidate is returned with its own rates; combined_rates is null. No single rate is chosen.
  • unmatched: nothing in the state's files matches, or a jurisdiction's rate is missing for the date (reason: rate_missing).
  • unsupported: the state is not published, or the date is outside the published range.

Matching. match.method says how the result was found and match.confidence how specific it is:

  • address_range (confidence high, or medium when a directional or street suffix had to be ignored): the street, house number and parity fall inside one of the state's address ranges.
  • zip4 (medium): the ZIP+4 range record. Used when the address is not in the state's address ranges, or for ZIP+4 lookups.
  • zip5 (medium when every record of the ZIP agrees; otherwise the result is ambiguous, confidence low).

Lookups fall back from address to ZIP+4 to 5-digit ZIP, as the SST guide prescribes; match.attempted lists the methods tried and a fallback_used notice says when an address was answered from ZIP records.

Address normalisation. Deterministic, no geocoding: the street line is upper-cased and punctuation removed; the first token is the house number (digits, optionally one letter); a unit designator (APT, UNIT, STE, LOT, #, ...) ends the street; a leading / trailing directional (N, NORTH, SW, ...) and a trailing USPS suffix (STREET -> ST, AVENUE -> AVE, ...) are split off and abbreviated; suffix words inside the name are abbreviated too (HIGHWAY 33 -> HWY 33). PO BOX n is supported. The state files are normalised the same way. data.normalized shows how the input was read.

Rates. Four rates per jurisdiction, as SST publishes them: general and food/drug, each intrastate (sale originating in the state) and interstate (originating outside it). Rates are exact decimal fractions (0.0725 = 7.25%). Food/drug rates are null where a state leaves them blank.

Provenance. Every jurisdiction rate and boundary record carries a provenance block: the SST file it came from (source_url, source_version = file name), that file's date, when this version was published and the validation status of the publication. Responses list the active publication in meta.datasets.

Authenticate with an API key in X-API-Key or Authorization: Bearer. The organization's plan must include sales-tax; requests count against its monthly quota. Every response carries X-Request-Id. Errors share the Error body.

Rates

Rates for a street address

GET/v1/sales-tax/rates/address

Looks the address up in the state's address ranges, then falls back to the ZIP+4 and 5-digit ZIP records (see Matching). state and street are required, plus zip or city (with zip the city is not used for matching).

Authentication: API key (X-API-Key or Bearer)

Parameters

NameInTypeDescription
streetrequiredquerystring

Street line, e.g. 100 Main St or PO Box 12. At most 100 characters.

Example: 100 Main St
cityquerystring

City, used for matching only when zip is absent. At most 60 characters.

staterequiredquerystring

2-letter state code. Unpublished states answer 200 with status unsupported.

zipqueryZipInput

5-digit ZIP or ZIP+4 (12345, 12345-6789 or 123456789).

datequerystring (date)

Day to look up (YYYY-MM-DD). Default today in America/New_York.

Example: 2026-10-20

Responses

200

The lookup result (see Results for each status).

LookupResponse
400

Invalid parameter (VALIDATION_ERROR; details.fields maps each parameter to the reason).

Error
401

Missing or invalid API key (UNAUTHORIZED), or a disabled, expired or revoked one (API_KEY_DISABLED, API_KEY_EXPIRED, API_KEY_REVOKED).

Error
403

Organization suspended (ORGANIZATION_SUSPENDED), no live subscription (NO_ACTIVE_SUBSCRIPTION), sales-tax not on the plan (PRODUCT_NOT_ENABLED) or a key scoped to another product (API_KEY_PRODUCT_SCOPE).

Error
429

Per-minute rate limit exceeded (RATE_LIMIT_EXCEEDED) or monthly quota exhausted (QUOTA_EXCEEDED).

Error
503

The sales tax dataset has no active publication yet (SERVICE_UNAVAILABLE, details.dataset_id).

Error
curl
curl -s "https://api.olympus.new-odyssey.com/v1/sales-tax/rates/address?street=100%20Main%20St" \
  -H "X-API-Key: $OLYMPUS_API_KEY"

Rates for a ZIP+4 or 5-digit ZIP

GET/v1/sales-tax/rates/zip/{zip}

With a ZIP+4, the ZIP+4 range record is used when the state publishes one, otherwise the 5-digit ZIP. A 5-digit ZIP that spans several jurisdiction sets returns every candidate as ambiguous, never just one. Without state, every published state is searched (some ZIPs cross state lines); a ZIP found nowhere whose prefix belongs to a state we do not publish is unsupported.

Authentication: API key (X-API-Key or Bearer)

Parameters

NameInTypeDescription
ziprequiredpathZipInput

5-digit ZIP or ZIP+4 (12345, 12345-6789 or 123456789).

statequerystring

Only search this state (2-letter code).

datequerystring (date)

Day to look up (YYYY-MM-DD). Default today in America/New_York.

Example: 2026-10-20

Responses

200

The lookup result.

LookupResponse
400

Invalid parameter (VALIDATION_ERROR; details.fields maps each parameter to the reason).

Error
401

Missing or invalid API key (UNAUTHORIZED), or a disabled, expired or revoked one (API_KEY_DISABLED, API_KEY_EXPIRED, API_KEY_REVOKED).

Error
403

Organization suspended (ORGANIZATION_SUSPENDED), no live subscription (NO_ACTIVE_SUBSCRIPTION), sales-tax not on the plan (PRODUCT_NOT_ENABLED) or a key scoped to another product (API_KEY_PRODUCT_SCOPE).

Error
429

Per-minute rate limit exceeded (RATE_LIMIT_EXCEEDED) or monthly quota exhausted (QUOTA_EXCEEDED).

Error
503

The sales tax dataset has no active publication yet (SERVICE_UNAVAILABLE, details.dataset_id).

Error
curl
curl -s "https://api.olympus.new-odyssey.com/v1/sales-tax/rates/zip/{zip}" \
  -H "X-API-Key: $OLYMPUS_API_KEY"

Jurisdictions

Every jurisdiction rate of a state on a date

GET/v1/sales-tax/states/{state}/jurisdictions

The state's rate file on the date: the state rate, county, city (municipality, town, village) and special district rates, each with its code, FIPS code where it has one, rates, effective dates and provenance. Rate rows are listed even when no boundary record assigns them. An unpublished state answers 200 with state.status: unsupported and an empty list.

Authentication: API key (X-API-Key or Bearer)

Parameters

NameInTypeDescription
staterequiredpathstring

2-letter state code.

levelqueryLevel

Only jurisdictions of this level.

datequerystring (date)

Day to look up (YYYY-MM-DD). Default today in America/New_York.

Example: 2026-10-20

Responses

200

The state's jurisdictions.

JurisdictionsResponse
400

Invalid parameter (VALIDATION_ERROR; details.fields maps each parameter to the reason).

Error
401

Missing or invalid API key (UNAUTHORIZED), or a disabled, expired or revoked one (API_KEY_DISABLED, API_KEY_EXPIRED, API_KEY_REVOKED).

Error
403

Organization suspended (ORGANIZATION_SUSPENDED), no live subscription (NO_ACTIVE_SUBSCRIPTION), sales-tax not on the plan (PRODUCT_NOT_ENABLED) or a key scoped to another product (API_KEY_PRODUCT_SCOPE).

Error
429

Per-minute rate limit exceeded (RATE_LIMIT_EXCEEDED) or monthly quota exhausted (QUOTA_EXCEEDED).

Error
503

The sales tax dataset has no active publication yet (SERVICE_UNAVAILABLE, details.dataset_id).

Error
curl
curl -s "https://api.olympus.new-odyssey.com/v1/sales-tax/states/{state}/jurisdictions" \
  -H "X-API-Key: $OLYMPUS_API_KEY"

Coverage

States served, their files and the data vintage

GET/v1/sales-tax/coverage

Every state and DC with its status: published (with the SST files, their effective quarter and checksum, the date range served and the matching methods its files support) or unsupported (reason sst_member_not_loaded or not_sst_member). Answers 200 even before anything is published; every state is then unsupported.

Authentication: API key (X-API-Key or Bearer)

Responses

200

Coverage.

CoverageResponse
401

Missing or invalid API key (UNAUTHORIZED), or a disabled, expired or revoked one (API_KEY_DISABLED, API_KEY_EXPIRED, API_KEY_REVOKED).

Error
403

Organization suspended (ORGANIZATION_SUSPENDED), no live subscription (NO_ACTIVE_SUBSCRIPTION), sales-tax not on the plan (PRODUCT_NOT_ENABLED) or a key scoped to another product (API_KEY_PRODUCT_SCOPE).

Error
429

Per-minute rate limit exceeded (RATE_LIMIT_EXCEEDED) or monthly quota exhausted (QUOTA_EXCEEDED).

Error
curl
curl -s "https://api.olympus.new-odyssey.com/v1/sales-tax/coverage" \
  -H "X-API-Key: $OLYMPUS_API_KEY"

Schemas

Error object

The error body shared by every Olympus service.

FieldTypeDescription
error *string

Human-readable message.

code *string

Stable machine-readable code.

productstring

Product that produced the error, when applicable.

detailsobject

ZipInput string

StateCode string

Rate number

Exact decimal fraction (0.0725 = 7.25%).

Date string (date)

Level enum: state | county | city | special

city covers municipalities, towns and villages (the place code of the SST boundary file).

statecountycityspecial

Status enum: matched | ambiguous | unmatched | unsupported

matchedambiguousunmatchedunsupported

Reason enum: state_not_supported | date_out_of_range | multiple_jurisdiction_sets | address_not_found | zip_not_found | rate_missing | address_not_found_zip_used | street_not_parsed_zip_used

Why the status is what it is: state_not_supported, date_out_of_range (unsupported); multiple_jurisdiction_sets (ambiguous); address_not_found, zip_not_found, rate_missing (unmatched); address_not_found_zip_used / street_not_parsed_zip_used (matched from ZIP records instead of an address range). Null for a direct match.

state_not_supporteddate_out_of_rangemultiple_jurisdiction_setsaddress_not_foundzip_not_foundrate_missingaddress_not_found_zip_usedstreet_not_parsed_zip_used

Method enum: address_range | zip4 | zip5

address_rangezip4zip5

Provenance object

Where this value came from and which publication introduced this version of it.

FieldTypeDescription
dataset_id *enum: plutus.sst_rates_boundaries
source_id *enum: sstgb.rate_boundary_files
source_url *string (uri)

The SST file the value was read from (https://www.streamlinedsalestax.org/ratesandboundry/...).

source_version *string

SST file name without extension, e.g. <ST>R2026Q4AUG21 (state, R rate or B boundary, effective quarter, posting date).

source_date *string (date) | null

Date of the file as served by the SST site (Last-Modified).

published_at *string (date-time)

When this version of the record was first published. Unchanged records keep their original time.

schema_version *string
validation_status *enum: passed | passed_with_warnings
record_id *string

Stable record key within the dataset, e.g. sst:<ST>:rate:<type>:<code>:<from>:<to>.

DatasetPublication object

FieldTypeDescription
dataset_id *string
publication_id *integer (int64)
published_at *string (date-time)
freshness *enum: fresh | stale

stale when the active publication is older than 100 days.

Notice object

FieldTypeDescription
code *enum: not_a_taxability_determination | multiple_jurisdictions | fallback_used | coverage_limited | not_published | state_specific
message *string

Meta object

FieldTypeDescription
request_idstring
datasets *DatasetPublication []

Active publication of the dataset this response read (empty before the first publication).

notices *Notice []

Caveats about this response. Always includes not_a_taxability_determination.

Rates object

FieldTypeDescription
general_intrastate *Rate

General rate on sales originating in the state.

general_interstate *Rate

General rate on sales originating outside the state.

food_drug_intrastate *number | null

Food and drug rate (intrastate); null when the state leaves it blank.

food_drug_interstate *number | null

Jurisdiction object

FieldTypeDescription
level *Level
code *string

Code in the state's files (state FIPS, county FIPS, place code or state special district code).

fips *string | null

State FIPS followed by the county or place code, as the state publishes it (Census place or county subdivision code). Null for special districts.

jurisdiction_type *string | null

X12 data element 1721 type of taxing authority (45 state, 00 county, 01 city, ...). Null when no rate row resolves it.

jurisdiction_type_name *string | null
rates *Rates | null

Null when the rate file has no single rate for this jurisdiction on the date.

effective_from *string (date) | null
effective_to *string (date) | null

Last day the rate applies; null when open-ended.

provenance *Provenance | null

Boundary object

FieldTypeDescription
record_type *enum: A | 4 | Z

SST record type of the representative record (A address range, 4 ZIP+4 range, Z 5-digit ZIP).

records *object

How many records of each type assign this jurisdiction set in the matched area.

effective_from *string (date)
effective_to *string (date) | null
city_name *string | null
composite_ser_code *string | null

Composite reporting code for states that require one (reporting only; not a rate).

provenance *Provenance

Candidate object

One set of jurisdictions that may apply, with its rates.

FieldTypeDescription
state_code *StateCode
complete *boolean

Every jurisdiction has exactly one rate on the date.

combined_rates *Rates | null

Sum of the jurisdictions' rates; null unless complete. Not the tax due on a transaction.

sst_default *boolean

The state's ZIP+4 (zip4 lookups) or 5-digit ZIP (zip5 lookups) record assigns this set. States assign the lowest combined rate in the area to that record; it is not necessarily the rate at a given address.

jurisdictions *Jurisdiction []
boundary *Boundary

StateRef object

FieldTypeDescription
code *StateCode
name *string
status *enum: published | unsupported

LookupResult object

FieldTypeDescription
status *Status
reason *Reason
date *string (date)

The day looked up.

normalized *object

How the input was read (null fields were absent or did not parse).

state *StateRef | null

The state looked up (for ZIP lookups, the state found or the ZIP prefix's state).

match *object
combined_rates *Rates | null

Set only when status is matched. Not the tax due on a transaction.

candidates *Candidate []

One per jurisdiction set found (exactly one when matched, several when ambiguous, none when nothing was found).

LookupResponse object

FieldTypeDescription
data *LookupResult
meta *Meta

JurisdictionsResponse object

FieldTypeDescription
data *object
meta *Meta

FileRef object

FieldTypeDescription
name *string

SST file name, e.g. <ST>B2026Q4AUG21.zip.

effective_quarter *string
url *string (uri)
sha256 *string

CoverageState object

FieldTypeDescription
code *StateCode
name *string
fips *string
status *enum: published | unsupported
reason *enum: sst_member_not_loaded | not_sst_member | null
sst_participant *boolean

The state posts SST rate and boundary files.

dates_from *string (date) | null
dates_to *string (date) | null

Last date served for this state: the end of its newest file quarter, or of the latest quarter whose SST posting deadline (the first day of the month before the quarter) had passed when the files were loaded, whichever is later.

match_methods *Method []

Matching methods the state's files support.

files *object | null
rows *object | null

Rate rows, boundary records effective on the load date by type, and rejected lines.

provenance *Provenance | null

CoverageResponse object

FieldTypeDescription
data *object
meta *Meta

* required field