diff --git a/docs/content/modules/taxes/admin/manage-tax-rates.mdx b/docs/content/modules/taxes/admin/manage-tax-rates.mdx new file mode 100644 index 0000000000..f1a290524c --- /dev/null +++ b/docs/content/modules/taxes/admin/manage-tax-rates.mdx @@ -0,0 +1,1088 @@ +--- +description: 'Learn how to manage tax rates of a region using the admin APIs. This includes managing tax rates and their associations with products, product types, or shipping options.' +addHowToData: true +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# How to Manage Tax Rates + +In this document, you’ll learn how to manage tax rates of a region using the admin APIs. + +## Overview + +Tax rates are created per region. Each region has a default tax rate and code. However, you can create more tax rates for a region that have a different code or specific conditions. For example, you can override the default tax rate for a specific product type, product, or shipping option. + +### Scenario + +You want to add or use the following admin functionalities: + +- Manage tax rates. This includes listing tax rates, and creating, updating, and deleting a tax rate. +- Add or delete a tax rate’s association with products, product types, or shipping options. + +--- + +## Prerequisites + +### Medusa Components + +It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the [quickstart guide](../../../development/backend/install.mdx) to get started. + +### JS Client + +This guide includes code snippets to send requests to your Medusa backend using Medusa’s JS Client, among other methods. + +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client](../../../js-client/overview.md) installed and have [created an instance of the client](../../../js-client/overview.md#configuration). + +### Medusa React + +This guide also includes code snippets to send requests to your Medusa backend using Medusa React, among other methods. + +If you follow the Medusa React code blocks, it's assumed you already have [Medusa React installed](../../../medusa-react/overview.md) and have [used MedusaProvider higher in your component tree](../../../medusa-react/overview.md#usage). + +### Authenticated Admin User + +You must be an authenticated admin user before following along with the steps in the tutorial. + +You can learn more about [authenticating as an admin user in the API reference](/api/admin/#section/Authentication). + +--- + +## List Tax Rates + +You can list the tax rates by sending a request to the [List Tax Rates endpoint](/api/admin#tag/Tax-Rates/operation/GetTaxRates): + + + + +```ts +medusa.admin.taxRates.list() +.then(({ tax_rates, limit, offset, count }) => { + console.log(tax_rates.length) +}) +``` + + + + +```tsx +import { useAdminTaxRates } from "medusa-react" + +const TaxRates = () => { + const { tax_rates, isLoading } = useAdminTaxRates() + + return ( +
+ {isLoading && Loading...} + {tax_rates && !tax_rates.length && ( + No Tax Rates + )} + {tax_rates && tax_rates.length > 0 && ( +
    + {tax_rates.map((tax_rate) => ( +
  • {tax_rate.code}
  • + ))} +
+ )} +
+ ) +} + +export default TaxRates +``` + +
+ + +```ts +fetch(`/admin/tax-rates`, { + credentials: "include", +}) +.then((response) => response.json()) +.then(({ tax_rates, limit, offset, count }) => { + console.log(tax_rates.length) +}) +``` + + + + +```bash +curl -L -X GET '/admin/tax-rates' \ +-H 'Authorization: Bearer ' +``` + + +
+ +You can pass to this endpoint filter and search parameters as explained in the [API reference](/api/admin#tag/Tax-Rates/operation/GetTaxRates). + +The endpoint returns an array of tax rate objects along with [pagination parameters](/api/admin#section/Pagination). + +### Listing Tax Rates for a Region + +You can retrieve the tax rate of a region by passing the `region_id` query parameter: + + + + +```ts +medusa.admin.taxRates.list({ + region_id: "reg_123", +}) +.then(({ tax_rates, limit, offset, count }) => { + console.log(tax_rates.length) +}) +``` + + + + +```tsx +import { useAdminTaxRates } from "medusa-react" + +const TaxRates = () => { + const { tax_rates, isLoading } = useAdminTaxRates({ + region_id: "reg_123", + }) + + return ( +
+ {isLoading && Loading...} + {tax_rates && !tax_rates.length && ( + No Tax Rates + )} + {tax_rates && tax_rates.length > 0 && ( +
    + {tax_rates.map((tax_rate) => ( +
  • {tax_rate.code}
  • + ))} +
+ )} +
+ ) +} + +export default TaxRates +``` + +
+ + +```ts +fetch(`/admin/tax-rates?region_id=reg_123`, { + credentials: "include", +}) +.then((response) => response.json()) +.then(({ tax_rates, limit, offset, count }) => { + console.log(tax_rates.length) +}) +``` + + + + +```bash +curl -L -X GET '/admin/tax-rates?region_id=reg_123' \ +-H 'Authorization: Bearer ' +``` + + +
+ +In the example above, you pass the region’s ID as the value of the `region_id` query parameter. + +This query parameter also accepts an array of strings, allowing you to filter the tax rates by more than one region: + + + + +```ts +medusa.admin.taxRates.list({ + region_id: ["reg_123", "reg_456"], +}) +.then(({ tax_rates, limit, offset, count }) => { + console.log(tax_rates.length) +}) +``` + + + + +```tsx +import { useAdminTaxRates } from "medusa-react" + +const TaxRates = () => { + const { tax_rates, isLoading } = useAdminTaxRates({ + region_id: ["reg_123", "reg_456"], + }) + + return ( +
+ {isLoading && Loading...} + {tax_rates && !tax_rates.length && ( + No Tax Rates + )} + {tax_rates && tax_rates.length > 0 && ( +
    + {tax_rates.map((tax_rate) => ( +
  • {tax_rate.code}
  • + ))} +
+ )} +
+ ) +} + +export default TaxRates +``` + +
+ + + + +```ts +fetch(`/admin/tax-rates?region_id[]=reg_123®ion_id[]=reg_456`, { + credentials: "include", +}) +.then((response) => response.json()) +.then(({ tax_rates, limit, offset, count }) => { + console.log(tax_rates.length) +}) +``` + + + + +```bash +curl -L -X GET '/admin/tax-rates?region_id[]=reg_123®ion_id[]=reg_456' \ +-H 'Authorization: Bearer ' +``` + + +
+ +--- + +## Create Tax Rate + +You can create a tax rate by sending a request to the [Create Tax Rate endpoint](/api/admin#tag/Tax-Rates/operation/PostTaxRates): + + + + +```ts +medusa.admin.taxRates.create({ + code: "TEST", + name: "New Tax Rate", + region_id, + rate: 10, +}) +.then(({ tax_rate }) => { + console.log(tax_rate.id) +}) +``` + + + + +```tsx +import { useAdminCreateTaxRate } from "medusa-react" + +const CreateTaxRate = () => { + const createTaxRate = useAdminCreateTaxRate() + // ... + + const handleCreate = () => { + createTaxRate.mutate({ + code: "TEST", + name: "New Tax Rate", + region_id, + rate: 10, + }) + } + + // ... +} + +export default CreateTaxRate +``` + + + + +```ts +fetch(`/admin/tax-rates`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + code: "TEST", + name: "New Tax Rate", + region_id, + rate: 10, + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.id) +}) +``` + + + + +```bash +curl -L -X POST '/admin/tax-rates' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "code": "TEST", + "name": "New Tax Rate", + "region_id": "", + "rate": 10 +}' +``` + + + + +This endpoint requires the following body parameters: + +- `code`: a string indicating the tax code +- `name`: a string indicating the name of the tax rate +- `region_id`: a string indicating the region this tax rate belongs to + +You can optionally pass other parameters, such as `rate`, which is a number that indicates the tax rate. Refer to the [API reference](/api/admin#tag/Tax-Rates/operation/PostTaxRates) for other optional parameters. + +:::tip + +You can specify here the products, product types, or shipping options that this tax rate is created for as explained in the API reference. In this guide, you’ll be using other endpoints to add or delete these conditions on a tax rate. + +::: + +The request returns the created tax rate as an object. + +--- + +## Update Tax Rate + +You can update a tax rate by sending a request to the [Update Tax Rate endpoint](/api/admin#tag/Tax-Rates/operation/PostTaxRatesTaxRate): + + + + +```ts +medusa.admin.taxRates.update(taxRateId, { + name: "New Tax Rate", +}) +.then(({ tax_rate }) => { + console.log(tax_rate.id) +}) +``` + + + + +```tsx +import { useAdminUpdateTaxRate } from "medusa-react" + +const UpdateTaxRate = () => { + const updateTaxRate = useAdminUpdateTaxRate(taxRateId) + // ... + + const handleUpdate = () => { + updateTaxRate.mutate({ + name: "New Tax Rate", + }) + } + + // ... +} + +export default UpdateTaxRate +``` + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: "New Tax Rate", + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.id) +}) +``` + + + + +```bash +curl -L -X POST '/admin/tax-rates/' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "name": "New Tax Rate" +}' +``` + + + + +This endpoint requires the tax rate ID to be passed as a path parameter. + +In the request body, you can pass any of the tax rate’s fields as a parameter. In the example above, you pass the `name` parameter to update the name of the tax rate. Refer to the [API reference](/api/admin#tag/Tax-Rates/operation/PostTaxRatesTaxRate) for other parameters you can pass in the request body. + +The request returns the updated tax rate as an object. + +--- + +## Manage Tax Rate’s Products + +This section explains how you can add and remove products from a tax rate. + +### Add Product to Tax Rate + +You can add a product to a tax rate by sending a request to the [Add Products endpoint](/api/admin#tag/Tax-Rates/operation/PostTaxRatesTaxRateProducts): + + + + +```ts +medusa.admin.taxRates.addProducts(taxRateId, { + products: [ + productId1, + ], +}) +.then(({ tax_rate }) => { + console.log(tax_rate.products) +}) +``` + + + + +```tsx +import { useAdminCreateProductTaxRates } from "medusa-react" + +const AddProduct = () => { + const addProduct = useAdminCreateProductTaxRates(taxRateId) + // ... + + const handleAdd = () => { + addProduct.mutate({ + products: [ + productId1, + ], + }) + } + + // ... +} + +export default AddProduct +``` + + + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}/products/batch`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + products: [ + productId1, + ], + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.products) +}) +``` + + + + +```bash +curl -L -X POST '/admin/tax-rates//products/batch' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "products": [ + "" + ] +}' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +In the request body, the `products` parameter is required. It’s an array of strings, each string being the ID of a product to add to the tax rate. + +The request returns the updated tax rate as an object. You can access the tax rate’s products using the `products` property of the tax rate object. + +### Remove Product from Tax Rate + +You can remove a product from a tax rate by sending a request to the [Delete Products endpoint](/api/admin#tag/Tax-Rates/operation/DeleteTaxRatesTaxRateProducts): + + + + +```ts +medusa.admin.taxRates.removeProducts(taxRateId, { + products: [ + productId1, + ], +}) +.then(({ tax_rate }) => { + console.log(tax_rate.products) +}) +``` + + + + +```tsx +import { useAdminDeleteProductTaxRates } from "medusa-react" + +const RemoveProduct = () => { + const removeProduct = useAdminDeleteProductTaxRates(taxRateId) + // ... + + const handleRemove = () => { + removeProduct.mutate({ + products: [ + productId1, + ], + }) + } + + // ... +} + +export default RemoveProduct +``` + + + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}/products/batch`, { + credentials: "include", + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + products: [ + productId1, + ], + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.products) +}) +``` + + + + +```bash +curl -L -X DELETE '/admin/tax-rates//products/batch' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "products": [ + "" + ] +}' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +In the request body, the `products` parameter is required. It’s an array of strings, each string being the ID of a product to remove from the tax rate. + +The request returns the updated tax rate as an object. You can access the tax rate’s products using the `products` property of the tax rate object. + +--- + +## Manage Tax Rate’s Product Types + +This section explains how you can add and remove product types from a tax rate. + +### Add Product Type to Tax Rate + +You can add a product type to a tax rate by sending a request to the [Add Product Types endpoint](/api/admin#tag/Tax-Rates/operation/PostTaxRatesTaxRateProductTypes): + + + + +```ts +medusa.admin.taxRates.addProductTypes(taxRateId, { + product_types: [ + productTypeId, + ], +}) +.then(({ tax_rate }) => { + console.log(tax_rate.product_types) +}) +``` + + + + +```tsx +import { + useAdminCreateProductTypeTaxRates, +} from "medusa-react" + +const AddProductTypes = () => { + const addProductTypes = useAdminCreateProductTypeTaxRates( + taxRateId + ) + // ... + + const handleAdd = () => { + addProductTypes.mutate({ + product_types: [ + productTypeId, + ], + }) + } + + // ... +} + +export default AddProductTypes +``` + + + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}/product-types/batch`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + product_types: [ + productTypeId, + ], + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.product_types) +}) +``` + + + + +```bash +curl -L -X POST '/admin/tax-rates//product-types/batch' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "product_types": [ + "" + ] +}' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +In the request body, the `product_types` parameter is required. It’s an array of strings, each string being the ID of a product type to add to the tax rate. + +The request returns the updated tax rate as an object. You can access the tax rate’s product types using the `product_types` property of the tax rate object. + +### Remove Product Type from Tax Rate + +You can remove a product type from a tax rate by sending a request to the [Delete Product Types endpoint](/api/admin#tag/Tax-Rates/operation/DeleteTaxRatesTaxRateProductTypes): + + + + +```ts +medusa.admin.taxRates.removeProductTypes(taxRateId, { + product_types: [ + productTypeId, + ], +}) +.then(({ tax_rate }) => { + console.log(tax_rate.product_types) +}) +``` + + + + +```tsx +import { + useAdminDeleteProductTypeTaxRates, +} from "medusa-react" + +const RemoveProductTypes = () => { + const removeProductTypes = useAdminDeleteProductTypeTaxRates( + taxRateId + ) + // ... + + const handleRemove = () => { + removeProductTypes.mutate({ + product_types: [ + productTypeId, + ], + }) + } + + // ... +} + +export default RemoveProductTypes +``` + + + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}/product-types/batch`, { + credentials: "include", + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + product_types: [ + productTypeId, + ], + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.id) +}) +``` + + + + +```bash +curl -L -X DELETE '/admin/tax-rates//product-types/batch' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "product_types": [ + "" + ] +}' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +In the request body, the `product_types` parameter is required. It’s an array of strings, each string being the ID of a product type to remove from the tax rate. + +The request returns the updated tax rate as an object. You can access the tax rate’s product types using the `product_types` property of the tax rate object. + +--- + +## Manage Tax Rate’s Shipping Options + +This section explains how you can add and remove shipping options from a tax rate. + +### Add Shipping Option to Tax Rate + +You can add a shipping option to a tax rate by sending a request to the [Add Shipping Option endpoint](/api/admin#tag/Tax-Rates/operation/PostTaxRatesTaxRateShippingOptions): + + + + +```ts +medusa.admin.taxRates.addShippingOptions(taxRateId, { + shipping_options: [ + shippingOptionId, + ], +}) +.then(({ tax_rate }) => { + console.log(tax_rate.shipping_options) +}) +``` + + + + +```tsx +import { useAdminCreateShippingTaxRates } from "medusa-react" + +const AddShippingOptions = () => { + const addShippingOption = useAdminCreateShippingTaxRates( + taxRateId + ) + // ... + + const handleAdd = () => { + addShippingOption.mutate({ + shipping_options: [ + shippingOptionId, + ], + }) + } + + // ... +} + +export default AddShippingOptions +``` + + + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}/shipping-options/batch`, { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + shipping_options: [ + shippingOptionId, + ], + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.shipping_options) +}) +``` + + + + +```bash +curl -L -X POST '/admin/tax-rates//shipping-options/batch' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "shipping_options": [ + "" + ] +}' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +In the request body, the `shipping_options` parameter is required. It’s an array of strings, each string being the ID of a shipping option to add to the tax rate. + +The request returns the updated tax rate as an object. You can access the tax rate’s shipping options using the `shipping_options` property of the tax rate object. + +### Remove Shipping Options from Tax Rate + +You can remove a shipping option from a tax rate by sending a request to the [Delete Shipping Options endpoint](/api/admin#tag/Tax-Rates/operation/DeleteTaxRatesTaxRateShippingOptions): + + + + +```ts +medusa.admin.taxRates.removeShippingOptions(taxRateId, { + shipping_options: [ + shippingOptionId, + ], +}) +.then(({ tax_rate }) => { + console.log(tax_rate.shipping_options) +}) +``` + + + + +```tsx +import { useAdminDeleteShippingTaxRates } from "medusa-react" + +const RemoveShippingOptions = () => { + const removeShippingOptions = useAdminDeleteShippingTaxRates( + taxRateId + ) + // ... + + const handleRemove = () => { + removeShippingOptions.mutate({ + shipping_options: [ + shippingOptionId, + ], + }) + } + + // ... +} + +export default RemoveShippingOptions +``` + + + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}/shipping-options/batch`, { + credentials: "include", + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + shipping_options: [ + shippingOptionId, + ], + }), +}) +.then((response) => response.json()) +.then(({ tax_rate }) => { + console.log(tax_rate.shipping_options) +}) +``` + + + + +```bash +curl -L -X DELETE '/admin/tax-rates//shipping-options/batch' \ +-H 'Authorization: Bearer ' \ +-H 'Content-Type: application/json' \ +--data-raw '{ + "shipping_options": [ + "" + ] +}' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +In the request body, the `shipping_options` parameter is required. It’s an array of strings, each string being the ID of a shipping option to remove from the tax rate. + +The request returns the updated tax rate as an object. You can access the tax rate’s shipping options using the `shipping_options` property of the tax rate object. + +--- + +## Delete Tax Rate + +You can delete a tax rate by sending a request to the [Delete Tax Rate endpoint](/api/admin#tag/Tax-Rates/operation/DeleteTaxRatesTaxRate): + + + + +```ts +medusa.admin.taxRates.delete(taxRateId) +.then(({ id, object, deleted }) => { + console.log(id) +}) +``` + + + + +```tsx +import { useAdminDeleteTaxRate } from "medusa-react" + +const DeleteTaxRate = () => { + const deleteTaxRate = useAdminDeleteTaxRate(taxRateId) + // ... + + const handleDelete = () => { + deleteTaxRate.mutate() + } + + // ... +} + +export default DeleteTaxRate +``` + + + + +```ts +fetch(`/admin/tax-rates/${taxRateId}`, { + credentials: "include", + method: "DELETE", +}) +.then((response) => response.json()) +.then(({ id, object, deleted }) => { + console.log(id) +}) +``` + + + + +```bash +curl -L -X DELETE '/admin/tax-rates/' \ +-H 'Authorization: Bearer ' +``` + + + + +This endpoint requires the tax rate’s ID as a path parameter. + +The request returns the following fields: + +- `id`: The ID of the deleted tax rate. +- `object`: The type of object that was deleted. In this case, the value will be `tax-rate`. +- `deleted`: A boolean value indicating whether the tax rate was deleted. + +--- + +## See Also + +- [How to manage tax settings using admin APIs](./manage-tax-settings.mdx) diff --git a/docs/content/modules/taxes/overview.mdx b/docs/content/modules/taxes/overview.mdx index 05f1ba3fd9..aaa273cd91 100644 --- a/docs/content/modules/taxes/overview.mdx +++ b/docs/content/modules/taxes/overview.mdx @@ -82,25 +82,14 @@ Admins can create additional tax rates aside from the default tax rate. They can Customers can review order edit requests and authorize additional payments if necessary. -