Support
Configure taxesConfigure your taxes

How to configure your taxes

View as Markdown

Create and manage tax rates through the Tax GraphQL subgraph — the store-scoped endpoint for all tax configuration operations.

Overview

Tax rates define what percentage is applied to purchases in your store. All Tax operations (reads, creates, status changes, and deletes) are GraphQL queries and mutations sent to POST /v2/commerce/stores/{storeId}/tax-subgraph. Send x-store-id on every request — that header is what the Tax subgraph authorizes against. If the header is missing, GraphQL returns AUTHENTICATION_ERROR (Failed to authorize) with HTTP 200. If the path {storeId} and header disagree, the header wins.

The Tax subgraph also supports Classifications, Jurisdictions, and Overrides for more advanced tax configurations. This article covers the core rate operations. Go to the Tax GraphQL reference for the full schema.

Prerequisites

The following prerequisites are required before you can configure taxes:

  • a GoDaddy account with an active commerce store
  • a Personal Access Token (PAT) with the scopes for the operations you need (commerce.tax:read for queries; commerce.tax:create, :write, or :delete for the corresponding mutations)
  • your storeId

    Find your store ID

    Go to Your stores to find your store ID.

List tax rates

rates(first, after, ...) returns a paginated collection of rates. Results use edge-based cursor pagination. Go to Paginate results for cursor-based pagination guidance. Optional orderBy takes exactly one of id, name, createdAt, or updatedAt with ASC or DESC — not "desc", and not two keys in one object.

The following procedure retrieves the first page of tax rates.

  1. Query the first 10 tax rates:
curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/tax-subgraph" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "x-store-id: ${STORE_ID}" \
  -H "Content-Type: application/json" \
  -d '{"query": "query GetRates($first: Int) { rates(first: $first) { edges { node { id name label status value { __typename ... on RatePercentage { percentage } ... on RateAmount { amount { value currencyCode } } } } } pageInfo { hasNextPage endCursor } } }", "variables": {"first": 10}}'
  1. Review the paginated response:
{
  "data": {
    "rates": {
      "edges": [
        {
          "node": {
            "id": "<TAX_RATE_ID>",
            "name": "<TAX_RATE_NAME>",
            "label": "<TAX_RATE_DISPLAY_LABEL>",
            "status": "<TAX_RATE_STATUS>",
            "value": {
              "__typename": "RatePercentage",
              "percentage": "<RATE_PERCENTAGE>"
            }
          }
        }
      ],
      "pageInfo": {
        "hasNextPage": false,
        "endCursor": "<PAGINATION_CURSOR>"
      }
    }
  }
}

Get a tax rate

rate(id: ID!) retrieves a single tax rate by its ID.

The following procedure reads a single tax rate by ID.

  • Retrieve a tax rate by its id:
RATE_ID="<TAX_RATE_ID>"

curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/tax-subgraph" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "x-store-id: ${STORE_ID}" \
  -H "Content-Type: application/json" \
  -d "{\"query\": \"query GetRate(\$id: ID!) { rate(id: \$id) { id name label status value { __typename ... on RatePercentage { percentage } ... on RateAmount { amount { value currencyCode } } } createdAt } }\", \"variables\": {\"id\": \"${RATE_ID}\"}}"

Create a tax rate

createRate(input: MutationCreateRateInput!) creates a new rate. label and value are required. name is generated from the label when omitted. status defaults to ACTIVE. value is a RateValueInput: set percentage (string, out of 100) or amount ({ value, currencyCode }), not both. For amount.value, send integer minor units (850, not 8.5).

Optional input fields from the schema: calculationMethod (ADDITIVE or INCLUSIVE; defaults to ADDITIVE), description, jurisdictionId, metafields, and references. You can omit metafields and references entirely. If you send metafields, the array must be nonempty — [] is rejected. Don't send createdAt or updatedAt — those fields exist only for Tax v1 to v2 migration. For metafields, prefer type: "string" (lowercase).

When you read a rate, value is a union. Select it with inline fragments (... on RatePercentage / ... on RateAmount) — there is no value { rate } field.

The following procedure creates a new tax rate.

  1. Create a tax rate with a label and value:
curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/tax-subgraph" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "x-store-id: ${STORE_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation CreateRate($input: MutationCreateRateInput!) { createRate(input: $input) { id name label status createdAt } }",
    "variables": {
      "input": {
        "label": "<TAX_RATE_DISPLAY_LABEL>",
        "name": "<TAX_RATE_UNIQUE_NAME>",
        "value": { "percentage": "8.5" }
      }
    }
  }'
  1. Save the id from the response (you'll need it to activate or modify the rate):
{
  "data": {
    "createRate": {
      "id": "<TAX_RATE_ID>",
      "name": "<TAX_RATE_UNIQUE_NAME>",
      "label": "<TAX_RATE_DISPLAY_LABEL>",
      "status": "ACTIVE",
      "createdAt": "<ISO8601_CREATED_TIMESTAMP>"
    }
  }
}

Activate a tax rate

activateRate(id: ID!) sets a rate's status to ACTIVE. Requires commerce.tax:write.

The following procedure activates an existing tax rate.

  1. Activate a rate by its id:
RATE_ID="<TAX_RATE_ID>"

curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/tax-subgraph" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "x-store-id: ${STORE_ID}" \
  -H "Content-Type: application/json" \
  -d "{\"query\": \"mutation ActivateRate(\$id: ID!) { activateRate(id: \$id) { id label status activatedAt } }\", \"variables\": {\"id\": \"${RATE_ID}\"}}"
  1. Confirm the rate status updated to ACTIVE:
{
  "data": {
    "activateRate": {
      "id": "<TAX_RATE_ID>",
      "label": "<TAX_RATE_DISPLAY_LABEL>",
      "status": "ACTIVE",
      "activatedAt": "<ISO8601_ACTIVATED_TIMESTAMP>"
    }
  }
}

Deactivate a tax rate

deactivateRate(id: ID!) sets a rate's status to INACTIVE. Requires commerce.tax:write. Deactivated rates no longer apply to purchases.

The following procedure deactivates an active tax rate.

  1. Deactivate a rate by its id:
RATE_ID="<TAX_RATE_ID>"

curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/tax-subgraph" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "x-store-id: ${STORE_ID}" \
  -H "Content-Type: application/json" \
  -d "{\"query\": \"mutation DeactivateRate(\$id: ID!) { deactivateRate(id: \$id) { id label status } }\", \"variables\": {\"id\": \"${RATE_ID}\"}}"
  1. Confirm the rate status updated to INACTIVE:
{
  "data": {
    "deactivateRate": {
      "id": "<TAX_RATE_ID>",
      "label": "<TAX_RATE_DISPLAY_LABEL>",
      "status": "INACTIVE"
    }
  }
}

Delete a tax rate

deleteRate(id: ID!) permanently removes a tax rate. Requires commerce.tax:delete. This action can't be undone. Use deactivateRate instead if you might need the rate again.

The following procedure deletes a tax rate.

  1. Delete a rate by its id:
RATE_ID="<TAX_RATE_ID>"

curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/tax-subgraph" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "x-store-id: ${STORE_ID}" \
  -H "Content-Type: application/json" \
  -d "{\"query\": \"mutation DeleteRate(\$id: ID!) { deleteRate(id: \$id) { id label } }\", \"variables\": {\"id\": \"${RATE_ID}\"}}"
  1. deleteRate returns the deleted Rate object. Selecting no subfields is a GraphQL validation error (Field "deleteRate" of type "Rate" must have a selection of subfields).
{
  "data": {
    "deleteRate": {
      "id": "<TAX_RATE_ID>",
      "label": "<TAX_RATE_DISPLAY_LABEL>"
    }
  }
}

Common errors

StatusMost likely causeNote
200 with errors[].extensions.code: AUTHENTICATION_ERRORx-store-id is missing or is not a store this token can access.Authorization uses the header, not the path {storeId}.
400GraphQL selection or variables are invalid.deleteRate must select fields on Rate. Rate.value is a union — use ... on RatePercentage / ... on RateAmount.
401PAT is missing or expired. Go to Authentication to generate a new token.
403Token doesn't include the required scope for the operation.
404Tax rate ID doesn't exist or isn't accessible with the provided token.
429Rate limit exceeded.Honor the Retry-After header before retrying.

Agent & Automation Notes

Scopescommerce.tax:read, commerce.tax:create, commerce.tax:write, commerce.tax:delete
IdempotentNo
DestructiveNo
On failureQuery operations are safe to retry. For mutations, check the current rate state with the rates query before retrying to avoid duplicate creates.

Last updated on

How is this guide?

On this page