ReferenceReference by module

Tax API

Every Tax action (7) and data model (4): endpoints, scopes, input, preconditions, events and examples.

Tax rates by country and product type, applied to every sale.

Module code tax · 7 actions · 4 data models · 4 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: tax (everything), tax:read (read only) or tax:<capability>.

Resources

ResourceTableList and readPOSTPATCHDELETE
tax_classestax_class/api/v1/tax_classes
tax_configuration_countriestax_configuration_country/api/v1/tax_configuration_countries
tax_configurationstax_configuration/api/v1/tax_configurations
tax_ratestax_rate/api/v1/tax_rates

Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.

Actions

ActionNeedsWhat it does
tax.archive_classtax:manageArchive a tax class
tax.remove_country_exceptiontax:manageRemove a country exception
tax.remove_ratetax:manageRemove a tax rate
tax.save_classtax:manageSave a tax class
tax.save_configurationtax:manageSave tax configuration
tax.set_country_exceptiontax:manageSet a country exception
tax.set_ratetax:manageSet a tax rate

tax.archive_class

Archive a tax class — Takes a class out of use without rewriting any document it already priced.

Needs tax:manage · changes data

POSThttps://app.getera.io/api/v1/tax_classes/{id}/actions/archive_class
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.archive_class

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Tax class · id of tax_class
archivedbooleanyesArchived

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
tax_class_not_foundThe class must exist.

Events it publishes: tax.class_archived

What it writes: tax_class (update) — Archives or restores it

curl -X POST https://app.getera.io/api/v1/tax_classes/TAX_CLASSE_ID/actions/archive_class \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"archived":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.class_archived"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxClasses.archiveClass("TAX_CLASSE_ID", {
  archived: true
})
era tax_classes archive_class TAX_CLASSE_ID \
  --archived true
tools/call
{
  "name": "era__tax__archive_class",
  "arguments": {
    "id": "TAX_CLASSE_ID",
    "archived": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 tax_class_not_found · 429 slow down

tax.remove_country_exception

Remove a country exception — The country falls back to the configuration it belongs to.

Needs tax:manage · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/tax_configuration_countries/{id}/actions/remove_country_exception
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.remove_country_exception

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Exception · id of tax_configuration_country

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
tax_exception_not_foundThe exception must exist.

Events it publishes: tax.configuration_changed

What it writes: tax_configuration_country (delete) — Removes the exception

curl -X POST https://app.getera.io/api/v1/tax_configuration_countries/TAX_CONFIGURATION_COUNTRY_ID/actions/remove_country_exception \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.configuration_changed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxConfigurationCountries.removeCountryException("TAX_CONFIGURATION_COUNTRY_ID")
era tax_configuration_countries remove_country_exception TAX_CONFIGURATION_COUNTRY_ID
tools/call
{
  "name": "era__tax__remove_country_exception",
  "arguments": {
    "id": "TAX_CONFIGURATION_COUNTRY_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 tax_exception_not_found · 429 slow down

tax.remove_rate

Remove a tax rate — Removes one country rate. Documents already priced keep their snapshot.

Needs tax:manage · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/tax_rates/{id}/actions/remove_rate
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.remove_rate

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Rate · id of tax_rate

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
tax_rate_not_foundThe rate must exist.

Events it publishes: tax.rate_changed

What it writes: tax_rate (delete) — Removes the rate

curl -X POST https://app.getera.io/api/v1/tax_rates/TAX_RATE_ID/actions/remove_rate \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.rate_changed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxRates.removeRate("TAX_RATE_ID")
era tax_rates remove_rate TAX_RATE_ID
tools/call
{
  "name": "era__tax__remove_rate",
  "arguments": {
    "id": "TAX_RATE_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 tax_rate_not_found · 429 slow down

tax.save_class

Save a tax class — Creates or renames a tax class — the category a price is taxed under.

Needs tax:manage · changes data

POSThttps://app.getera.io/api/v1/tax_classes/{id}/actions/save_class
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.save_class

Input

FieldTypeRequiredNotes
iduuidFilled from the path {id} · Tax class · id of tax_class
namestringyesName · max 255
descriptionstringDescription · max 2000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
tax_class_not_foundThe class being renamed must exist.
tax_class_name_takenTwo tax classes cannot share a name.

Events it publishes: tax.class_saved

What it writes: tax_class (upsert) — Writes the class

curl -X POST https://app.getera.io/api/v1/tax_classes/TAX_CLASSE_ID/actions/save_class \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name":"Name"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.class_saved"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxClasses.saveClass("TAX_CLASSE_ID", {
  name: "Name"
})
era tax_classes save_class TAX_CLASSE_ID \
  --name "Name"
tools/call
{
  "name": "era__tax__save_class",
  "arguments": {
    "id": "TAX_CLASSE_ID",
    "name": "Name"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 tax_class_not_found, tax_class_name_taken · 429 slow down

tax.save_configuration

Save tax configuration — Whether and how tax is charged — for the workspace, or for one sales channel.

Needs tax:manage · changes data

POSThttps://app.getera.io/api/v1/tax_configurations/actions/save_configuration
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.save_configuration

Input

FieldTypeRequiredNotes
channelIduuidChannel
chargeTaxesbooleanyesCharge taxes
calculationStrategystring (enum)Strategy · Allowed values: flat_rates, tax_app
displayGrossPricesbooleanShow prices with tax
pricesEnteredWithTaxbooleanPrices are entered with tax
taxAppIdstringTax app · max 256
useWeightedTaxForShippingbooleanWeighted tax for shipping

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
tax_app_id_requiredThe tax-app strategy needs the app that calculates it.

Events it publishes: tax.configuration_changed

What it writes: tax_configuration (upsert) — Writes the configuration

curl -X POST https://app.getera.io/api/v1/tax_configurations/actions/save_configuration \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"chargeTaxes":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.configuration_changed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxConfigurations.saveConfiguration({
  chargeTaxes: true
})
era tax_configurations save_configuration \
  --charge-taxes true
tools/call
{
  "name": "era__tax__save_configuration",
  "arguments": {
    "chargeTaxes": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 tax_app_id_required · 429 slow down

tax.set_country_exception

Set a country exception — Overrides the configuration for one country — Saleor’s TaxConfigurationPerCountry.

Needs tax:manage · changes data

POSThttps://app.getera.io/api/v1/tax_configuration_countries/actions/set_country_exception
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.set_country_exception

Input

FieldTypeRequiredNotes
configurationIduuidyesConfiguration · id of tax_configuration
countrystringyesCountry · max 2
chargeTaxesbooleanyesCharge taxes
calculationStrategystring (enum)Strategy · Allowed values: flat_rates, tax_app
displayGrossPricesbooleanShow prices with tax
taxAppIdstringTax app · max 256

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
invalid_countryThe country must be an ISO-3166 two-letter code.
tax_configuration_not_foundThe configuration must exist.

Events it publishes: tax.configuration_changed

What it writes: tax_configuration_country (upsert) — Writes the exception

curl -X POST https://app.getera.io/api/v1/tax_configuration_countries/actions/set_country_exception \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"configurationId":"TAX_CONFIGURATION_ID","country":"Country","chargeTaxes":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.configuration_changed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxConfigurationCountries.setCountryException({
  configurationId: "TAX_CONFIGURATION_ID",
  country: "Country",
  chargeTaxes: true
})
era tax_configuration_countries set_country_exception \
  --configuration-id "TAX_CONFIGURATION_ID" \
  --country "Country" \
  --charge-taxes true
tools/call
{
  "name": "era__tax__set_country_exception",
  "arguments": {
    "configurationId": "TAX_CONFIGURATION_ID",
    "country": "Country",
    "chargeTaxes": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 invalid_country, tax_configuration_not_found · 429 slow down

tax.set_rate

Set a tax rate — The rate for one country — for a class, or the country default when no class is given.

Needs tax:manage · changes data

POSThttps://app.getera.io/api/v1/tax_rates/actions/set_rate
API key or OAuth token · tax:manage
  • Canonical address: POST /api/v1/actions/tax.set_rate

Input

FieldTypeRequiredNotes
taxClassIduuidTax class · id of tax_class
countrystringyesCountry · max 2
ratenumberyesRate (%) · min 0 · max 100

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
invalid_countryThe country must be an ISO-3166 two-letter code.
tax_class_not_foundThe class must exist.

Events it publishes: tax.rate_changed

What it writes: tax_rate (upsert) — Writes the rate

curl -X POST https://app.getera.io/api/v1/tax_rates/actions/set_rate \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"country":"Country","rate":1}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "tax.rate_changed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.taxRates.setRate({
  country: "Country",
  rate: 1
})
era tax_rates set_rate \
  --country "Country" \
  --rate 1
tools/call
{
  "name": "era__tax__set_rate",
  "arguments": {
    "country": "Country",
    "rate": 1
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold tax:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 invalid_country, tax_class_not_found · 429 slow down

Data models

TaxClass

Table tax_class · Resource tax_classes

  • GET /api/v1/tax_classes
  • GET /api/v1/tax_classes/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
namestring · text
descriptionstring · textyes
archived_atstring (date-time) · timestamptzyes
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK ((length(TRIM(BOTH FROM name)) > 0))

TaxConfigurationCountry

Table tax_configuration_country · Resource tax_configuration_countries

  • GET /api/v1/tax_configuration_countries
  • GET /api/v1/tax_configuration_countries/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
tax_configuration_idstring (uuid) · uuidtax_configuration
countrystring · bpcharmax 2
charge_taxesboolean · bool
calculation_strategystring · textyes
display_gross_pricesboolean · bool
tax_app_idstring · textyes
use_weighted_tax_for_shippingboolean · bool
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Unique: tax_configuration_id, country

Checks:

  • CHECK (((calculation_strategy IS NULL) OR (calculation_strategy = ANY (ARRAY['flat_rates'::text, 'tax_app'::text]))))
  • CHECK ((country ~ '^[A-Z]{2}$'::text))

TaxConfiguration

Table tax_configuration · Resource tax_configurations

  • GET /api/v1/tax_configurations
  • GET /api/v1/tax_configurations/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
channel_idstring (uuid) · uuidyes
charge_taxesboolean · bool
calculation_strategystring · textflat_rates, tax_app
display_gross_pricesboolean · bool
prices_entered_with_taxboolean · bool
tax_app_idstring · textyes
use_weighted_tax_for_shippingboolean · bool
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK (((calculation_strategy <> 'tax_app'::text) OR (tax_app_id IS NOT NULL)))

TaxRate

Table tax_rate · Resource tax_rates

  • GET /api/v1/tax_rates
  • GET /api/v1/tax_rates/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
tax_class_idstring (uuid) · uuidyestax_class
countrystring · bpcharmax 2
ratestring (decimal) · numeric
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK ((country ~ '^[A-Z]{2}$'::text))
  • CHECK (((rate >= (0)::numeric) AND (rate <= (100)::numeric)))

Events

Workflows and webhooks react to these events.

EventWhat happensPayload
tax.class_archivedA tax class was archived or restored.id, archived
tax.class_savedA tax class was created or renamed.id, name
tax.configuration_changedHow tax is charged changed.id, channelId, country
tax.rate_changedA country rate changed.id, country, taxClassId, rate
Was this page helpful?