docs: publish restructure (#3496)
* docs: added features and guides overview page * added image * added version 2 * added version 3 * added version 4 * docs: implemented new color scheme * docs: redesigned sidebar (#3193) * docs: redesigned navbar for restructure (#3199) * docs: redesigned footer (#3209) * docs: redesigned cards (#3230) * docs: redesigned admonitions (#3231) * docs: redesign announcement bar (#3236) * docs: redesigned large cards (#3239) * docs: redesigned code blocks (#3253) * docs: redesigned search modal and page (#3264) * docs: redesigned doc footer (#3268) * docs: added new sidebars + refactored css and assets (#3279) * docs: redesigned api reference sidebar * docs: refactored css * docs: added code tabs transition * docs: added new sidebars * removed unused assets * remove unusued assets * Fix deploy errors * fix incorrect link * docs: fixed code responsivity + missing icons (#3283) * docs: changed icons (#3296) * docs: design fixes to the sidebar (#3297) * redesign fixes * docs: small design fixes * docs: several design fixes after restructure (#3299) * docs: bordered icon fixes * docs: desgin fixes * fixes to code blocks and sidebar scroll * design adjustments * docs: restructured homepage (#3305) * docs: restructured homepage * design fixes * fixed core concepts icon * docs: added core concepts page (#3318) * docs: restructured homepage * design fixes * docs: added core concepts page * changed text of different components * docs: added architecture link * added missing prop for user guide * docs: added regions overview page (#3327) * docs: added regions overview * moved region pages to new structure * docs: fixed description of regions architecture page * small changes * small fix * docs: added customers overview page (#3331) * docs: added regions overview * moved region pages to new structure * docs: fixed description of regions architecture page * small changes * small fix * docs: added customers overview page * fix link * resolve link issues * docs: updated regions architecture image * docs: second-iteration fixes (#3347) * docs: redesigned document * design fixes * docs: added products overview page (#3354) * docs: added carts overview page (#3363) * docs: added orders overview (#3364) * docs: added orders overview * added links in overview * docs: added vercel redirects * docs: added soon badge for cards (#3389) * docs: resolved feedback changes + organized troubleshooting pages (#3409) * docs: resolved feedback changes * added extra line * docs: changed icons for restructure (#3421) * docs: added taxes overview page (#3422) * docs: added taxes overview page * docs: fix sidebar label * added link to taxes overview page * fixed link * docs: fixed sidebar scroll (#3429) * docs: added discounts overview (#3432) * docs: added discounts overview * fixed links * docs: added gift cards overview (#3433) * docs: added price lists overview page (#3440) * docs: added price lists overview page * fixed links * docs: added sales channels overview page (#3441) * docs: added sales overview page * fixed links * docs: added users overview (#3443) * docs: fixed sidebar border height (#3444) * docs: fixed sidebar border height * fixed svg markup * docs: added possible solutions to feedback component (#3449) * docs: added several overview pages + restructured files (#3463) * docs: added several overview pages * fixed links * docs: added feature flags + PAK overview pages (#3464) * docs: added feature flags + PAK overview pages * fixed links * fix link * fix link * fixed links colors * docs: added strategies overview page (#3468) * docs: automated upgrade guide (#3470) * docs: automated upgrade guide * fixed vercel redirect * docs: restructured files in docs codebase (#3475) * docs: restructured files * docs: fixed eslint exception * docs: finished restructure loose-ends (#3493) * fixed uses of backend * docs: finished loose ends * eslint fixes * fixed links * merged master * added update instructions for v1.7.12
This commit is contained in:
@@ -0,0 +1,799 @@
|
||||
---
|
||||
description: 'Learn how to implement sales channels features for admins in Medusa using the REST APIs. This includes how to list sales channels, and create, retrieve, update and delete a sales channel. This also includes how to manage products in a sales channel.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# How to Manage Sales Channels
|
||||
|
||||
In this document, you’ll learn how to manage sales channels and their products and orders using the Admin APIs.
|
||||
|
||||
:::note
|
||||
|
||||
If you’re looking to learn more in-depth about what Sales Channels are and how they work, check out [this documentation](../sales-channels.md) instead.
|
||||
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
Using Medusa’s Admin APIs, you can manage Sales Channels including creating, retrieving, updating, and deleting sales channels. You can also manage their products and orders.
|
||||
|
||||
This guide explains how to perform all these operations using the Admin APIs.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [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 installed](../../../js-client/overview.md) 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 this guide.
|
||||
|
||||
You can learn more about [authenticating as an admin user in the API reference](/api/admin/#section/Authentication).
|
||||
|
||||
---
|
||||
|
||||
## Create Sales Channels
|
||||
|
||||
You can create a sales channel by sending a request to the Create a Sales Channel endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.create({
|
||||
name: "App",
|
||||
description: "Mobile app",
|
||||
})
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useAdminCreateSalesChannel } from "medusa-react"
|
||||
|
||||
const CreateSalesChannel = () => {
|
||||
const createSalesChannel = useAdminCreateSalesChannel()
|
||||
// ...
|
||||
|
||||
const handleCreate = (name: string, description: string) => {
|
||||
createSalesChannel.mutate({
|
||||
name,
|
||||
description,
|
||||
})
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default CreateSalesChannel
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/admin/sales-channels`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: "App",
|
||||
description: "Mobile app",
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X POST '<BACKEND_URL>/admin/sales-channels' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
name: 'App',
|
||||
description: 'Mobile app'
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This request requires the request body parameters `name`, and optionally accepts the `description` and `is_disabled` request body parameters.
|
||||
|
||||
It returns the created sales channel.
|
||||
|
||||
---
|
||||
|
||||
## List Sales Channels
|
||||
|
||||
You can list all sales channels by sending a request to the List Sales Channels endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.list()
|
||||
.then(({ sales_channels, limit, offset, count }) => {
|
||||
console.log(sales_channels.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { SalesChannel } from "@medusajs/medusa"
|
||||
import { useAdminSalesChannels } from "medusa-react"
|
||||
|
||||
const SalesChannels = () => {
|
||||
const { sales_channels, isLoading } = useAdminSalesChannels()
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isLoading && <span>Loading...</span>}
|
||||
{sales_channels && !sales_channels.length && (
|
||||
<span>No Sales Channels</span>
|
||||
)}
|
||||
{sales_channels && sales_channels.length > 0 && (
|
||||
<ul>
|
||||
{sales_channels.map((salesChannel: SalesChannel) => (
|
||||
<li key={salesChannel.id}>{salesChannel.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesChannels
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/admin/sales-channels`, {
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ sales_channels, limit, offset, count }) => {
|
||||
console.log(sales_channels.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X GET '<BACKEND_URL>/admin/sales-channels' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This request returns an array of all sales channels in your store. You can also pass query parameters to filter or customize the pagination of the results. Check out [the API Reference for a full list of query parameters.](/api/admin/#tag/Sales-Channel/operation/GetSalesChannels)
|
||||
|
||||
---
|
||||
|
||||
## Retrieve a Sales Channel
|
||||
|
||||
You can retrieve a sales channel’s details by its ID using the Get Sales Channel endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.retrieve(salesChannelId)
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useAdminSalesChannel } from "medusa-react"
|
||||
|
||||
const SalesChannel = () => {
|
||||
const {
|
||||
sales_channel,
|
||||
isLoading,
|
||||
} = useAdminSalesChannel(salesChannelId)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isLoading && <span>Loading...</span>}
|
||||
{sales_channel && <span>{sales_channel.name}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesChannel
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/admin/sales-channels/${salesChannelId}`, {
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ sales_channels, limit, offset, count }) => {
|
||||
console.log(sales_channels.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X GET '<BACKEND_URL>/admin/sales-channels/<SALES_CHANNEL_ID>' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This request returns the sales channel with the specified ID.
|
||||
|
||||
---
|
||||
|
||||
## Update a Sales Channel
|
||||
|
||||
You can update a Sales Channel’s details and attributes by sending a request to the Update Sales Channel endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.update(salesChannelId, {
|
||||
is_disabled: false,
|
||||
})
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useAdminUpdateSalesChannel } from "medusa-react"
|
||||
|
||||
const UpdateSalesChannel = () => {
|
||||
const updateSalesChannel = useAdminUpdateSalesChannel(
|
||||
salesChannelId
|
||||
)
|
||||
// ...
|
||||
|
||||
const handleUpdate = () => {
|
||||
updateSalesChannel.mutate({
|
||||
is_disabled: false,
|
||||
})
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default UpdateSalesChannel
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/admin/sales-channels/${salesChannelId}`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
is_disabled: false,
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X POST '<BACKEND_URL>/admin/sales-channels/<SALES_CHANNEL_ID>' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"is_disabled": false
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
In this example, you enable a sales channel by changing the value of the `is_disabled` attribute.
|
||||
|
||||
This request returns the updated sales channel.
|
||||
|
||||
You can check out [the API Reference for a full list of body parameters](/api/admin/#tag/Sales-Channel/operation/PostSalesChannelsSalesChannel) that you can pass to this request.
|
||||
|
||||
---
|
||||
|
||||
## Delete a Sales Channel
|
||||
|
||||
You can delete a sales channel by sending a request to the Delete Sales Channel endpoint with the ID of the sales channel to delete:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.delete(salesChannelId)
|
||||
.then(({ id, object, deleted }) => {
|
||||
console.log(id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useAdminDeleteSalesChannel } from "medusa-react"
|
||||
|
||||
const SalesChannel = () => {
|
||||
const deleteSalesChannel = useAdminDeleteSalesChannel(
|
||||
salesChannelId
|
||||
)
|
||||
// ...
|
||||
|
||||
const handleDelete = () => {
|
||||
deleteSalesChannel.mutate()
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default SalesChannel
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/admin/sales-channels/${salesChannelId}`, {
|
||||
method: "DELETE",
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ id, object, deleted }) => {
|
||||
console.log(id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X DELETE '<BACKEND_URL>/admin/sales-channels/<SALES_CHANNEL_ID>' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The ID of the deleted sales channel is returned in the response.
|
||||
|
||||
---
|
||||
|
||||
## Manage Products
|
||||
|
||||
### Add Product to a Sales Channel
|
||||
|
||||
To add a product to a sales channel, send a request to the Sales Channel’s Add Products endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.addProducts(salesChannelId, {
|
||||
product_ids: [
|
||||
{
|
||||
id: productId,
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useAdminAddProductsToSalesChannel } from "medusa-react"
|
||||
|
||||
const SalesChannel = () => {
|
||||
const addProducts = useAdminAddProductsToSalesChannel(
|
||||
salesChannelId
|
||||
)
|
||||
// ...
|
||||
|
||||
const handleAddProducts = (productId: string) => {
|
||||
addProducts.mutate({
|
||||
product_ids: [
|
||||
{
|
||||
id: productId,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default SalesChannel
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
<!-- eslint-disable max-len -->
|
||||
|
||||
```ts
|
||||
fetch(
|
||||
`<BACKEND_URL>/admin/sales-channels/${salesChannelId}/products/batch`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
product_ids: [
|
||||
{
|
||||
id: productId,
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X POST '<BACKEND_URL>/admin/sales-channels/<SALES_CHANNEL_ID>/products/batch' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"product_ids": [
|
||||
{
|
||||
"id": "<PRODUCT_ID>"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This request accepts the `product_ids` body parameter, which is an array of objects. Each object in the array must have an `id` property with the ID of the product to add as a value.
|
||||
|
||||
This request returns the sales channel.
|
||||
|
||||
### List Products Available in a Sales Channel
|
||||
|
||||
You can list the products available in a sales channel by sending a request to the List Products endpoint and passing the `sales_channel_id` query parameter to filter by a specific sales channel:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.products.list({
|
||||
sales_channel_id: [
|
||||
salesChannelId,
|
||||
],
|
||||
})
|
||||
.then(({ products, limit, offset, count }) => {
|
||||
console.log(products.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { Product } from "@medusajs/medusa"
|
||||
import {
|
||||
PricedProduct,
|
||||
} from "@medusajs/medusa/dist/types/pricing"
|
||||
import { useAdminProducts } from "medusa-react"
|
||||
|
||||
const SalesChannelProducts = () => {
|
||||
const { products, isLoading } = useAdminProducts({
|
||||
sales_channel_id: [salesChannelId],
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isLoading && <span>Loading...</span>}
|
||||
{products && products.length > 0 && (
|
||||
<ul>
|
||||
{products.map(
|
||||
(product: (Product | PricedProduct)) => (
|
||||
<li key={product.id}>{product.title}</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)}
|
||||
{products && !products.length && (
|
||||
<span>No Products</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesChannelProducts
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
<!-- eslint-disable max-len -->
|
||||
|
||||
```ts
|
||||
fetch(
|
||||
`<BACKEND_URL>/admin/products?sales_channel_id[0]=${salesChannelId}`,
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then(({ products, limit, offset, count }) => {
|
||||
console.log(products.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X GET '<BACKEND_URL>/admin/products?sales_channel_id[0]=<SALES_CHANNEL_ID>' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The request returns an array of products that are available in the specified sales channel.
|
||||
|
||||
### Delete Products from a Sales Channel
|
||||
|
||||
:::info
|
||||
|
||||
Deleting a product from a sales channel doesn't delete it completely. It only makes it unavailable in that sales channel.
|
||||
|
||||
:::
|
||||
|
||||
You can delete a product from a sales channel by sending a request to the Sales Channel’s Delete Products endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
<!-- eslint-disable max-len -->
|
||||
|
||||
```ts
|
||||
medusa.admin.salesChannels.removeProducts(salesChannelId, {
|
||||
product_ids: [
|
||||
{
|
||||
id: productId,
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import {
|
||||
useAdminDeleteProductsFromSalesChannel,
|
||||
} from "medusa-react"
|
||||
|
||||
const SalesChannel = () => {
|
||||
const deleteProducts = useAdminDeleteProductsFromSalesChannel(
|
||||
salesChannelId
|
||||
)
|
||||
// ...
|
||||
|
||||
const handleDeleteProducts = (productId: string) => {
|
||||
deleteProducts.mutate({
|
||||
product_ids: [
|
||||
{
|
||||
id: productId,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default SalesChannel
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
<!-- eslint-disable max-len -->
|
||||
|
||||
```ts
|
||||
fetch(
|
||||
`<BACKEND_URL>/admin/sales-channels/${salesChannelId}/products/batch`,
|
||||
{
|
||||
method: "DELETE",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
product_ids: [
|
||||
{
|
||||
id: productId,
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then(({ sales_channel }) => {
|
||||
console.log(sales_channel.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X DELETE '<BACKEND_URL>/admin/sales-channels/<SALES_CHANNEL_ID>/products/batch' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"product_ids": [
|
||||
{
|
||||
"id": "<PRODUCT_ID>"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This request accepts the `product_ids` body parameter, which is an array of objects. Each object in the array must have an `id` property with the ID of the product to delete as a value.
|
||||
|
||||
This request returns the sales channel.
|
||||
|
||||
---
|
||||
|
||||
## List Orders by Sales Channels
|
||||
|
||||
You can filter orders by a specific sales channel by sending a request to the List Orders endpoint and passing the `sales_channel_id` query parameter to filter by a specific sales channel:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.admin.orders.list({
|
||||
sales_channel_id: [
|
||||
salesChannelId,
|
||||
],
|
||||
limit: 50,
|
||||
offset: 0,
|
||||
})
|
||||
.then(({ orders, limit, offset, count }) => {
|
||||
console.log(orders.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { Order } from "@medusajs/medusa"
|
||||
import { useAdminOrders } from "medusa-react"
|
||||
|
||||
const SalesChannelOrders = () => {
|
||||
const { orders, isLoading } = useAdminOrders({
|
||||
sales_channel_id: [salesChannelId],
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isLoading && <span>Loading...</span>}
|
||||
{orders && orders.length > 0 && (
|
||||
<ul>
|
||||
{orders.map((order: Order) => (
|
||||
<li key={order.id}>{order.display_id}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{orders && !orders.length && <span>No Orders</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SalesChannelOrders
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
<!-- eslint-disable max-len -->
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/admin/orders?sales_channel_id[0]=${salesChannelId}`, {
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ orders, limit, offset, count }) => {
|
||||
console.log(orders.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="curl" label="cURL">
|
||||
|
||||
```bash
|
||||
curl -L -X GET '<BACKEND_URL>/admin/orders?sales_channel_id[0]=<SALES_CHANNEL_ID>' \
|
||||
-H 'Authorization: Bearer <API_TOKEN>'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The request returns an array of orders that are associated with the specified sales channel.
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
description: "Sales channels are different methods a business offers its products for purchase for the customers. Learn about the available features and guides."
|
||||
---
|
||||
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
import DocCard from '@theme/DocCard';
|
||||
import Icons from '@theme/Icon';
|
||||
|
||||
# Sales Channels
|
||||
|
||||
Sales channels are different methods a business offers its products for purchase for the customers. This overview introduces the available features related to sales channels.
|
||||
|
||||
:::note
|
||||
|
||||
Not a developer? Check out the [Sales Channels user guide](../../user-guide/sales-channels/index.md).
|
||||
|
||||
:::
|
||||
|
||||
## Features
|
||||
|
||||
### Sales Channel Management
|
||||
|
||||
Admins can manage sales channels, creating an unlimited number of them. They specify the products’ availability for each sales channel.
|
||||
|
||||
<DocCardList colSize={4} items={[
|
||||
{
|
||||
type: 'link',
|
||||
href: '/modules/sales-channels/admin/manage',
|
||||
label: 'Admin: Manage Sales Channels',
|
||||
customProps: {
|
||||
icon: Icons['academic-cap-solid'],
|
||||
description: 'Learn how to manage sales channels using the Admin APIs.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/user-guide/sales-channels/manage',
|
||||
label: 'User Guide: Manage Sales Channels',
|
||||
customProps: {
|
||||
icon: Icons['users-solid'],
|
||||
description: 'Learn how to manage sales channels using Medusa Admin.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/user-guide/sales-channels/products',
|
||||
label: 'User Guide: Manage Products',
|
||||
customProps: {
|
||||
icon: Icons['users-solid'],
|
||||
description: 'Learn how to manage products in a sales channel using Medusa Admin.'
|
||||
}
|
||||
},
|
||||
]} />
|
||||
|
||||
### Sales Channels for Each Platform
|
||||
|
||||
Developers can associate a platform with a sales channel. For example, associating a storefront with a web sales channel. Only products available in that sales channel will be shown, and all orders placed on that sales channel will be associated with it.
|
||||
|
||||
Admins can filter orders by a sales channel. This would allow them to handle orders coming from each sales channel differently.
|
||||
|
||||
<DocCardList colSize={6} items={[
|
||||
{
|
||||
type: 'link',
|
||||
href: '/modules/sales-channels/storefront/use-sales-channels',
|
||||
label: 'Storefront: Use Sales Channels',
|
||||
customProps: {
|
||||
icon: Icons['academic-cap-solid'],
|
||||
description: 'Learn how to use sales channels in a storefront.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/modules/sales-channels/admin/manage#list-orders-by-sales-channels',
|
||||
label: 'Admin: Orders by Sales Channels',
|
||||
customProps: {
|
||||
icon: Icons['academic-cap-solid'],
|
||||
description: 'Learn how to filter orders by a sales channel.'
|
||||
}
|
||||
},
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
## Understand the Architecture
|
||||
|
||||
Learn how sales channel related entities and concepts are built, their relation to other modules, and more.
|
||||
|
||||
<DocCard item={{
|
||||
type: 'link',
|
||||
href: '/modules/sales-channels',
|
||||
label: 'Architecture: Sales Channel',
|
||||
customProps: {
|
||||
icon: Icons['circle-stack-solid'],
|
||||
description: 'Learn about the Sales Channels architecture.'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
---
|
||||
|
||||
## Related Modules
|
||||
|
||||
Discover Sales Channel’s relation to other modules in Medusa.
|
||||
|
||||
<DocCardList colSize={6} items={[
|
||||
{
|
||||
type: 'link',
|
||||
href: '/modules/products/overview',
|
||||
label: 'Product',
|
||||
customProps: {
|
||||
icon: Icons['tag-solid'],
|
||||
description: 'Products availability can be changed for each sales channel.'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/modules/orders/overview',
|
||||
label: 'Orders',
|
||||
customProps: {
|
||||
icon: Icons['shopping-cart-solid'],
|
||||
description: 'Orders can be associated and organized by a sales channel.'
|
||||
}
|
||||
},
|
||||
]} />
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
description: 'Learn what Sales Channels are and how they can be used in Medusa. Sales Channels allow merchants to separate between the different channels products are sold in.'
|
||||
---
|
||||
|
||||
# Sales Channels
|
||||
|
||||
In this document, you’ll learn about Sales Channels and how they can be used in Medusa.
|
||||
|
||||
## Introduction
|
||||
|
||||
Sales Channels allow you to separate between the different channels you sell products in. For example, you can have a sales channel for your website and another for your mobile apps.
|
||||
|
||||
Sales Channels are associated with stores, products, carts, and orders: A store has a default sales channel; you can define which products are available in a sales channel; you can specify the sales channel of a cart; you can filter orders by sales channel.
|
||||
|
||||
### Example Use Cases
|
||||
|
||||
The sales channel feature can be used in a variety of use cases including:
|
||||
|
||||
- Implement a B2B Ecommerce Store.
|
||||
- Specifying different products for each channel you sell in.
|
||||
- Support Omnichannel in your ecommerce store.
|
||||
|
||||
---
|
||||
|
||||
## SalesChannel Entity Overview
|
||||
|
||||
A sales channel is stored in the database as a [SalesChannel](../../references/entities/classes/SalesChannel.md) entity. Some of its important attributes are:
|
||||
|
||||
- `name`: The name of the sales channel.
|
||||
- `is_disabled`: A boolean value indicating of the Sales Channel is disabled or not.
|
||||
|
||||
---
|
||||
|
||||
## Relations to Other Entities
|
||||
|
||||
### Store
|
||||
|
||||
A store has a default sales channel. When you first run your Medusa backend or seed your database, a default sales channel is created, if it doesn’t exist, and associated with the store.
|
||||
|
||||
The relation is implemented in the [Store](../../references/entities/classes/Store.md) entity. You can access the default sales channel of a store by expanding the `default_sales_channel` relation and using `store.default_sales_channel`. You can also access the ID of the default sales channel using `store.default_sales_channel_id`.
|
||||
|
||||
### Product
|
||||
|
||||
Products can be available in more than one sales channel. You can then filter products by a sales channel using the Storefront and Admin APIs.
|
||||
|
||||
The relation is implemented in the [Product](../../references/entities/classes/Product.md) entity. You can access the sales channels a product is available in by expanding the `sales_channels` relation and using `product.sales_channels`.
|
||||
|
||||
### Cart
|
||||
|
||||
When you create a cart, you can optionally specify the sales channel it belongs to. If you don’t set the sales channel, the store’s default sales channel will be associated with it.
|
||||
|
||||
A cart can belong to only one sales channel. Only products that belong to the same sales channel as the cart can be added to it.
|
||||
|
||||
The relation is implemented in the [Cart](../../references/entities/classes/Cart.md) entity. You can access the sales channel a cart is associated with by expanding the `sales_channel` relation and using `cart.sales_channel`. You can also access the ID of the sales channel using `cart.sales_channel_id`.
|
||||
|
||||
### Order
|
||||
|
||||
Orders can optionally be associated with a sales channel. You can filter orders by a sales channel using the Storefront and Admin APIs.
|
||||
|
||||
The relation is implemented in the [Order](../../references/entities/classes/Order.md) entity. You can access the sales channel an order is associated with by expanding the `sales_channel` relation and using `order.sales_channel`. You can also access the ID of the sales channel using `order.sales_channel_id`.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Manage sales channels using the admin APIs](./admin/manage.mdx)
|
||||
- [Use sales channels in the storefront](./storefront/use-sales-channels.mdx)
|
||||
@@ -0,0 +1,256 @@
|
||||
---
|
||||
description: 'Learn how to implement sales channel functionalities in the storefront using REST APIs. This includes filtering products by Sales Channel and associating a cart with a sales channel.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# How to Use Sales Channels in Storefronts
|
||||
|
||||
In this document, you’ll learn how to use sales channels in your storefront.
|
||||
|
||||
## Overview
|
||||
|
||||
In your storefront, you can filter products by sales channels. You can also associate carts with a sales channel.
|
||||
|
||||
This guide explains how to perform these operations using the Storefront APIs.
|
||||
|
||||
### Alternative Approach: Publishable API keys
|
||||
|
||||
This guide covers how to pass the sales channel ID into different requests to retrieve or process data associated with the sales channel.
|
||||
|
||||
An alternative approach is to use Publishable API keys. You can learn how to use them in the following documents:
|
||||
|
||||
- [Using publishable API keys in requests](../../../development/publishable-api-keys/index.mdx)
|
||||
- Managing publishable API keys using [admin APIs](../../../development/publishable-api-keys/admin/manage-publishable-api-keys.mdx) or using [Medusa Admin](../../../user-guide/settings/publishable-api-keys.mdx)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Medusa Components
|
||||
|
||||
It's assumed that you already have a Medusa backend installed and set up. If not, you can follow our [quickstart guide](../../../development/backend/install.mdx) to get started.
|
||||
|
||||
It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../../starters/nextjs-medusa-starter.mdx) or [Gatsby](../../../starters/gatsby-medusa-starter.mdx) storefronts.
|
||||
|
||||
### 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 installed](../../../js-client/overview.md) 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).
|
||||
|
||||
For requests that use the cart, it's also assumed you already have [used CartProvider higher in your component tree](../../../medusa-react/overview.md#cartprovider).
|
||||
|
||||
---
|
||||
|
||||
## Filter Products by Sales Channel
|
||||
|
||||
To filter products by a specific sales channel, pass the `sales_channel_id` query parameter to the List Products endpoint:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.products.list({
|
||||
sales_channel_id: [
|
||||
salesChannelId,
|
||||
],
|
||||
})
|
||||
.then(({ products, limit, offset, count }) => {
|
||||
console.log(products.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { Product } from "@medusajs/medusa"
|
||||
import { useProducts } from "medusa-react"
|
||||
|
||||
const Products = () => {
|
||||
const { products, isLoading } = useProducts({
|
||||
sales_channel_id: [
|
||||
salesChannelId,
|
||||
],
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isLoading && <span>Loading...</span>}
|
||||
{products && products.length > 0 && (
|
||||
<ul>
|
||||
{products.map((product: Product) => (
|
||||
<li key={product.id}>{product.title}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{products && !products.length && <span>No Products</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Products
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
<!-- eslint-disable max-len -->
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/store/products?sales_channel_id[0]=${salesChannelId}`)
|
||||
.then((response) => response.json())
|
||||
.then(({ products, limit, offset, count }) => {
|
||||
console.log(products.length)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The `sales_channel_id` query parameter is an array of sales channel IDs. You can pass more than one sales channel.
|
||||
|
||||
The request returns an array of products. These are the products that are available in the sales channel.
|
||||
|
||||
---
|
||||
|
||||
## Associate a Cart with a Sales Channel
|
||||
|
||||
### When Creating a Cart
|
||||
|
||||
To associate a sales channel with a cart while creating it, you can pass the `sales_channel_id` request body parameter with the ID of the sales channel:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
|
||||
```ts
|
||||
medusa.carts.create({
|
||||
sales_channel_id: salesChannelId,
|
||||
})
|
||||
.then(({ cart }) => {
|
||||
console.log(cart.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useCart } from "medusa-react"
|
||||
|
||||
const Cart = () => {
|
||||
const { cart, createCart } = useCart()
|
||||
|
||||
const handleCreateCart = () => {
|
||||
createCart.mutate(
|
||||
{
|
||||
sales_channel_id: salesChannelId,
|
||||
},
|
||||
{
|
||||
onSuccess: ({ cart }) => {
|
||||
localStorage.setItem("cart_id", cart.id)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default Cart
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/store/carts`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sales_channel_id: salesChannelId,
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ cart }) => {
|
||||
console.log(cart.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The request returns the created cart.
|
||||
|
||||
### Updating an Existing Cart
|
||||
|
||||
You can update the sales channel of an existing cart by passing the `sales_channel_id` request body parameter with the ID of the sales channel:
|
||||
|
||||
<Tabs groupId="request-type" wrapperClassName="code-tabs">
|
||||
<TabItem value="client" label="Medusa JS Client" default>
|
||||
|
||||
```ts
|
||||
medusa.carts.update(cartId, {
|
||||
sales_channel_id: salesChannelId,
|
||||
})
|
||||
.then(({ cart }) => {
|
||||
console.log(cart.id)
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="medusa-react" label="Medusa React">
|
||||
|
||||
```tsx
|
||||
import { useCart } from "medusa-react"
|
||||
|
||||
const Cart = () => {
|
||||
// ...
|
||||
|
||||
const { updateCart } = useCart()
|
||||
|
||||
const changeSalesChannel = (salesChannelId: string) => {
|
||||
updateCart.mutate({
|
||||
sales_channel_id: salesChannelId,
|
||||
})
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default Cart
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="fetch" label="Fetch API">
|
||||
|
||||
```ts
|
||||
fetch(`<BACKEND_URL>/store/carts/${cartId}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sales_channel_id: salesChannelId,
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then(({ cart }) => console.log(cart.id))
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The request returns the updated cart.
|
||||
Reference in New Issue
Block a user