Skip to main content
Version: 3.0 (beta)

Channels

Introduction#

Since version 3.0, Saleor supports multiple sales channels. This feature allows the shop owner to configure many aspects of the store depending on the channel used.

  • Your store needs at least one channel to display products
  • You can add as many channels as you need
  • Each channel have exactly one currency
  • Channels can be deactivated for customers

Popular use cases:

  • If you sell internationally, you can use separate channels for different currencies or regions
  • If you want to have different prices in the custom mobile app and website, you can set up website-channel and mobile-channel

There are many models which can be customized per channel. Details which fields can be defined on a per-channel basis are defined in ChannelListing models:

Permissions#

Listing channels is allowed only for users with active is_staff flag.

Creating, editing, removing channel the MANAGE_CHANNELS permission is required. Changing ChannelListing does not require additional permissions. For example, changing Product availability requires only MANAGE_PRODUCTS.

Getting channel details#

Use channel query to get channel details.

Available fields:

  • id: Channel object ID
  • name: Channel name
  • isActive: Flag which changes if the channel is available for shop customers.
  • slug: When using channel depending queries, the slug is used for selecting the right one (for example when requesting Product details)
  • currencyCode: Currency code used by the channel.
  • defaultCountry: Default country for the channel. The default country will be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided, either as a query parameter or through a shipping address.
  • hasOrders: Returns true when there are already created orders using that channel. If that's the only channel using this currency, you won't be able to remove it

Request:

query {  channel(id: "Q2hhbm5lbDo3") {    id    isActive    name    slug    defaultCountry {      code      country    }    hasOrders  }}

Response:

{  "data": {    "channel": {      "id": "Q2hhbm5lbDo0MzM=",      "isActive": false,      "name": "Mobile",      "slug": "mobile",      "currencyCode": "USD",      "defaultCountry": {        "code": "US",        "country": "United States of America"      },      "hasOrders": false    }  }

Creating a new channel#

Creating a new channel is done using channelCreate mutation.

Request:

mutation {  channelCreate(    input: {      currencyCode: "USD"      defaultCountry: US      name: "Mobile"      slug: "mobile"    }  ) {    channel {      id      isActive      name      slug      currencyCode      defaultCountry {        code        country      }    }    errors {      code      field      message    }  }}

Response:

{  "data": {    "channelCreate": {      "channel": {        "id": "Q2hhbm5lbDo0MzM=",        "isActive": false,        "name": "Mobile",        "slug": "mobile",        "currencyCode": "USD",        "defaultCountry": {          "code": "US",          "country": "United States of America"        },      },      "errors": []    }  }}

Channel list#

Because some of the channels may be considered non-public (for example - channel for business partners), non-staff users can not use channels query.

Request:

query {  channels {    name  }}

Response:

{  "data": {    "channels": [      {        "name": "Mobile",      },      {        "name": "Website"      },    ]  }}

Activate / Deactivate channel#

If you want to make the channel unavailable for customers, you can change it's status to deactivated using channelDeactivate:

mutation {  channelDeactivate(id: "Q2hhbm5lbDoxMQ==") {    channel {      name      isActive    }    errors {      message    }  }}

Response:

{  "data": {    "channelDeactivate": {      "channel": {        "name": "Facebook",        "isActive": false      },      "channelErrors": []    }  }}

And to reverse the previous operation use channelActivate:

mutation {  channelActivate(id: "Q2hhbm5lbDoxMQ==") {    channel {      name      isActive    }    errors {      message    }  }}

Response:

{  "data": {    "channelDeactivate": {      "channel": {        "name": "Facebook",        "isActive": true      },      "channelErrors": []    }  }}

Removing a channel#

Channels can be removed only when:

  • There are no orders created in them.
  • If there are orders created, targetChannel is required. Its currency has to be as same as a channel you are about to delete. All orders will be moved to targetChannel.

channelDelete mutation takes input:

  • id: Channel ID which will be deleted
  • targetChannel: if there are existing orders, they will be moved into this channel
channelDelete(  id: ID!  input: ChannelDeleteInput): ChannelDelete
input ChannelDeleteInput {  targetChannel: ID!}

Errors#

type ChannelError {  field: String  message: String  code: ChannelErrorCode!}
enum ChannelErrorCode {  ALREADY_EXISTS  GRAPHQL_ERROR  INVALID  NOT_FOUND  REQUIRED  UNIQUE  CHANNEL_TARGET_ID_MUST_BE_DIFFERENT  CHANNELS_CURRENCY_MUST_BE_THE_SAME}

ChannelErrorCode values:

  • ALREADY_EXISTS: Object already exists in the database
  • GRAPHQL_ERROR: Wrong query
  • INVALID: Invalid data provided
  • NOT_FOUND: Could not found object
  • REQUIRED: Missing required fields
  • UNIQUE: Provided value for field needs to be unique
  • CHANNEL_TARGET_ID_MUST_BE_DIFFERENT: Cannot move orders into the channel you want to delete
  • CHANNELS_CURRENCY_MUST_BE_THE_SAME: Target channel has to have the same currency