Set up tax classes, zones, and rates
/admin/api/tax/classes
List all tax classes. Includes built-in classes (Standard, Reduced, Zero) and any custom classes.
/admin/api/tax/classes
Create a custom tax class.
/admin/api/tax/classes/{id}
Delete a custom tax class. Built-in classes (Standard, Reduced, Zero) cannot be deleted.
/admin/api/tax/zones
List all tax zones.
/admin/api/tax/zones
Create a new tax zone.
/admin/api/tax/zones/{id}
Update a tax zone's name and country list.
/admin/api/tax/zones/{id}
Delete a tax zone and its associated rates.
/admin/api/tax/zones/{id}/rates
List all tax rates for a specific zone.
/admin/api/tax/zones/{id}/rates
Set (upsert) tax rates for a zone. Each (zone, class) pair is created or updated. Rates are in basis points (e.g. 2000 = 20.00%).
/admin/api/tax/classes
List all tax classes. Includes built-in classes (Standard, Reduced, Zero) and any custom classes.
{
"classes": [
{
"id": 1,
"name": "Standard",
"created_at": "2025-11-01T00:00:00Z"
},
{
"id": 2,
"name": "Reduced",
"created_at": "2025-11-01T00:00:00Z"
},
{
"id": 3,
"name": "Zero",
"created_at": "2025-11-01T00:00:00Z"
}
]
}
curl "https://yourshop.zeroshop.io/admin/api/tax/classes" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/tax/classes",
headers={"Authorization": "Bearer zspat_..."}
)
classes = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/classes", {
headers: { "Authorization": "Bearer zspat_..." }
});
const data = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/classes")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(resp.body)
/admin/api/tax/classes
Create a custom tax class.
{
"name": "Digital Goods"
}
{
"id": 4,
"name": "Digital Goods",
"created_at": "2025-11-20T14:30:00Z"
}
curl -X POST "https://yourshop.zeroshop.io/admin/api/tax/classes" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{"name": "Digital Goods"}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/tax/classes",
headers={"Authorization": "Bearer zspat_..."},
json={"name": "Digital Goods"}
)
tax_class = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/classes", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "Digital Goods" })
});
const taxClass = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/classes")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { name: "Digital Goods" }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
tax_class = JSON.parse(resp.body)
/admin/api/tax/classes/{id}
Delete a custom tax class. Built-in classes (Standard, Reduced, Zero) cannot be deleted.
curl -X DELETE "https://yourshop.zeroshop.io/admin/api/tax/classes/4" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.delete(
"https://yourshop.zeroshop.io/admin/api/tax/classes/4",
headers={"Authorization": "Bearer zspat_..."}
)
assert resp.status_code == 204
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/classes/4", {
method: "DELETE",
headers: { "Authorization": "Bearer zspat_..." }
});
require "net/http"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/classes/4")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer zspat_..."
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
/admin/api/tax/zones
List all tax zones.
{
"zones": [
{
"id": 1,
"name": "EU",
"countries": [
"DE",
"FR",
"NL"
],
"created_at": "2025-11-20T14:30:00Z"
},
{
"id": 2,
"name": "United Kingdom",
"countries": [
"GB"
],
"created_at": "2025-11-19T09:15:00Z"
}
]
}
curl "https://yourshop.zeroshop.io/admin/api/tax/zones" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/tax/zones",
headers={"Authorization": "Bearer zspat_..."}
)
zones = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/zones", {
headers: { "Authorization": "Bearer zspat_..." }
});
const data = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/zones")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(resp.body)
/admin/api/tax/zones
Create a new tax zone.
{
"name": "EU",
"countries": [
"DE",
"FR",
"NL"
]
}
{
"id": 1,
"name": "EU",
"countries": [
"DE",
"FR",
"NL"
],
"created_at": "2025-11-20T14:30:00Z"
}
curl -X POST "https://yourshop.zeroshop.io/admin/api/tax/zones" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{
"name": "EU",
"countries": ["DE", "FR", "NL"]
}'
import requests
resp = requests.post(
"https://yourshop.zeroshop.io/admin/api/tax/zones",
headers={"Authorization": "Bearer zspat_..."},
json={"name": "EU", "countries": ["DE", "FR", "NL"]}
)
zone = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/zones", {
method: "POST",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "EU", countries: ["DE", "FR", "NL"] })
});
const zone = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/zones")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { name: "EU", countries: %w[DE FR NL] }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
zone = JSON.parse(resp.body)
/admin/api/tax/zones/{id}
Update a tax zone's name and country list.
{
"name": "European Union",
"countries": [
"DE",
"FR",
"NL",
"BE"
]
}
curl -X PUT "https://yourshop.zeroshop.io/admin/api/tax/zones/1" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{
"name": "European Union",
"countries": ["DE", "FR", "NL", "BE"]
}'
import requests
resp = requests.put(
"https://yourshop.zeroshop.io/admin/api/tax/zones/1",
headers={"Authorization": "Bearer zspat_..."},
json={"name": "European Union", "countries": ["DE", "FR", "NL", "BE"]}
)
assert resp.status_code == 204
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/zones/1", {
method: "PUT",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "European Union", countries: ["DE", "FR", "NL", "BE"] })
});
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/zones/1")
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { name: "European Union", countries: %w[DE FR NL BE] }.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
/admin/api/tax/zones/{id}
Delete a tax zone and its associated rates.
curl -X DELETE "https://yourshop.zeroshop.io/admin/api/tax/zones/1" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.delete(
"https://yourshop.zeroshop.io/admin/api/tax/zones/1",
headers={"Authorization": "Bearer zspat_..."}
)
assert resp.status_code == 204
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/zones/1", {
method: "DELETE",
headers: { "Authorization": "Bearer zspat_..." }
});
require "net/http"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/zones/1")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer zspat_..."
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
/admin/api/tax/zones/{id}/rates
List all tax rates for a specific zone.
{
"rates": [
{
"id": 1,
"zone_id": 1,
"class_id": 1,
"rate": 2000,
"created_at": "2025-11-20T14:30:00Z"
},
{
"id": 2,
"zone_id": 1,
"class_id": 2,
"rate": 700,
"created_at": "2025-11-20T14:30:00Z"
}
]
}
curl "https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates" \
-H "Authorization: Bearer zspat_..."
import requests
resp = requests.get(
"https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates",
headers={"Authorization": "Bearer zspat_..."}
)
rates = resp.json()
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates", {
headers: { "Authorization": "Bearer zspat_..." }
});
const data = await resp.json();
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer zspat_..."
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(resp.body)
/admin/api/tax/zones/{id}/rates
Set (upsert) tax rates for a zone. Each (zone, class) pair is created or updated. Rates are in basis points (e.g. 2000 = 20.00%).
{
"rates": [
{
"class_id": 1,
"rate": 2000
},
{
"class_id": 2,
"rate": 700
}
]
}
curl -X PUT "https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates" \
-H "Authorization: Bearer zspat_..." \
-H "Content-Type: application/json" \
-d '{
"rates": [
{"class_id": 1, "rate": 2000},
{"class_id": 2, "rate": 700}
]
}'
import requests
resp = requests.put(
"https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates",
headers={"Authorization": "Bearer zspat_..."},
json={"rates": [{"class_id": 1, "rate": 2000}, {"class_id": 2, "rate": 700}]}
)
assert resp.status_code == 204
const resp = await fetch("https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates", {
method: "PUT",
headers: {
"Authorization": "Bearer zspat_...",
"Content-Type": "application/json"
},
body: JSON.stringify({
rates: [
{ class_id: 1, rate: 2000 },
{ class_id: 2, rate: 700 }
]
})
});
require "net/http"
require "json"
uri = URI("https://yourshop.zeroshop.io/admin/api/tax/zones/1/rates")
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer zspat_..."
req["Content-Type"] = "application/json"
req.body = { rates: [{ class_id: 1, rate: 2000 }, { class_id: 2, rate: 700 }] }.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
We value your privacy
We use cookies for essential site functionality and, with your consent, analytics to understand how our platform is used. No personal data is shared with third parties. See our Privacy Policy for details.