# Stores

A store is the entity a seller sells through on a channel.
This page covers a store's lifecycle once it exists in Mirakl Connect:

* what state to report for it,
* how to keep its information up to date,
* which sub-channels it sells on,
* how to react when a seller links it or unlinks it.


## What a store is

In Mirakl Connect, everything a seller sells on a channel hangs off a store:

* offers are listed under it,
* orders are received against it,
* to link it or unlink it activates or deactivates the synchronization flows.


A store is identified within its channel, by a `channel_store_id` under a `channel_id`.

Channels do not all share that concept, so read a store as **the seller's selling entity on the channel**, whatever the channel calls it.
Two cases arise:

* **The channel has its own store-like entity**, such as a storefront, a shop, or a merchant account for each marketplace.
A seller can hold several, often one for each country, locale, or business unit, and each one becomes its own store in Mirakl Connect.
* **The channel has no store concept**, so the seller's channel account **is** the selling entity.
The store is then associated with that account, and the seller has a single store on your channel.


Mapping your channel's selling entity onto a Mirakl Connect store is your connector's responsibility, your connector assigns the `channel_store_id`.

Refer to [A note on identifiers](/content/product/connect-channel-platform/getting-started/data-model#a-note-on-identifiers).

## Pre-requisite: Import the store in Mirakl Connect

A seller's stores enter Mirakl Connect at the end of the channel authorization process, the only place that issues the token which authorizes their creation.

Refer to [Channel authorization](/content/product/connect-channel-platform/developer-guide/channel-authorization) for the import itself.

The sections below apply once a store exists.

## The store's state

The `state` field reports what your connector knows about the store on the channel: the store sells, the channel closed it, the channel suspended it, or your connector lost its access to it.
Both store APIs require the field:
[sellerAccountStoreCreate](/content/product/account-channel-platform/rest/connector/openapi3/store/seller_account_store_create) sets it as it imports the store, and [sellerAccountStoreUpdate](/content/product/account-channel-platform/rest/connector/openapi3/store/seller_account_store_update) changes it afterwards.

From the state and the suspension type, Mirakl Connect derives the **store status** that a seller sees.

Of the states you report, only `ACCESS_REVOKED` stops the store's catalog updates from reaching your connector.
The store keeps its catalog synchronized under every other state, a suspension included.

| `state` | `suspension_type` | Store status | Description |
|  --- | --- | --- | --- |
| `OPEN` | not read | `ONLINE` | The store sells on the channel. |
| `CLOSED`, `CLOSE`, or `TERMINATED` | not read | `CLOSED` | The store no longer sells on the channel, because the seller or the channel closed it. |
| `SUSPENDED` | absent, `null`, or `MANUAL` | `SUSPENDED` | The channel suspended a store that had been selling. Send `OPEN` once the channel lifts the suspension. |
| `SUSPENDED` | `SHOP_CREATION` | `PENDING_APPROVAL` | The store exists on the channel, and the channel has not approved it yet. It has never sold. |
| `ACCESS_REVOKED` | not read | `ACCESS_REVOKED` | Your connector holds no valid authorization to act for this store on the channel. Mirakl Connect stops the store's catalog updates, and the seller must [renew the channel authorization](/content/product/connect-channel-platform/developer-guide/channel-authorization#renewing-an-expiring-authorization). |


The match is exact and it is case sensitive, so `open` is not `OPEN`.

## Keeping store information up to date

A store's information changes over its life, such as its name, its state, or the date its channel access expires.
To push those changes, the connector calls the [sellerAccountStoreUpdate](/content/product/account-channel-platform/rest/connector/openapi3/store/seller_account_store_update) API, and identifies the store by its `channel_id` and its `channel_store_id`.

This call needs no token from the consent process.
Your connector's own credentials authorize it, so you can make the call at any time for as long as the store exists.

The call replaces the store information, so it is not a patch.
Send the current value of every field, `state` and `suspension_type` included.
A call that omits `suspension_type` for a suspended store clears the suspension type.

For more information, refer to the [REST APIs reference](/content/product/account-channel-platform/rest/connector/openapi3).

## Sub-channels

Some channels run several sales channels under one marketplace, and a seller can sell on more than one of them from a single catalog. A **sub-channel** is one of those sales channels.

A channel splits its sales channels on whatever line its business needs, and two splits are the most frequent:

* **By country**: one sales channel for each market the marketplace serves.
* **By business model**: one sales channel for the B2C buyers, and another for the B2B buyers.
The products are the same, and the prices and the selling conditions differ.


Which model a seller meets is the channel's own choice.
A channel that gives the seller a separate selling entity for each market turns each one into its own store, and a channel that keeps one selling entity with several sales channels turns those into sub-channels.

**Reading which model the channel applies, and mapping it onto stores and sub-channels, is your connector's responsibility.**
Settle it before you import the seller's stores, because the two models produce a different number of stores for the same seller.

**The seller's catalog is what decides between the two models.**
In Mirakl Connect, a product always lives under a store, and never under a sub-channel.
So ask whether the seller lists the same products on every sales channel:

* **The same products, and only the price or the stock differs.**
Use one store, with one sub-channel for each sales channel.
* **A different set of products for each sales channel.**
Use one store for each sales channel, and no sub-channel.


A store that sells on a single sales channel needs no sub-channel at all.

Each sub-channel carries three required fields:

* `id`: the sub-channel's identifier on the channel.
Every other call and event names this same value `sub_channel_code`.
* `name`: the name a seller reads in Mirakl Connect.
* `currency`: the sub-channel's currency, in ISO 4217 format.


The declaration changes the granularity of some data flows:

* **The prices and the stock can be per sub-channel.**
The channel chooses that in its catalog configuration, and [PriceStockUpsertEvent](/content/product/connect-channel-platform/webhooks/webhook/webhooks/pricestockupsertevent) then carries a `sub_channel` block.
Read [Price and stock lifecycle](/content/product/connect-channel-platform/developer-guide/catalog-configuration#price-and-stock-lifecycle).
* **The products stay per store.**
A [ProductUpsertEvent](/content/product/connect-channel-platform/webhooks/webhook/webhooks/productupsertevent) arrives once for the store, whatever the number of sub-channels.
* **An order belongs to one sub-channel.**
Read [Naming the sub-channel of an order](/content/product/connect-channel-platform/developer-guide/orders#naming-the-sub-channel-of-an-order).


### Declaring the sub-channels

Your connector sends the list on [upsertBusinessInformation](/content/product/connect-channel-platform/rest/connect/openapi3/store/upsertbusinessinformation), in the `sub_channels` array, together with the rest of the business information.

Two different operations answer on the path `PUT /v1/channels/{channel_id}/stores/{channel_store_id}`, one for each contract.
`sub_channels` belongs to `upsertBusinessInformation`, which Mirakl Connect serves.
`sellerAccountStoreUpdate`, which the Mirakl Account host serves, carries no sub-channel.

The array is a full replacement, like the rest of the call:

* To add a sub-channel, add it to the array.
* To update one, send it again with the same `id`.
* To remove one, leave it out of the array.


Four rules govern the writes:

* **An array that has been filled cannot be emptied.**
A call that sends `sub_channels` as `null`, or as an empty array, on a store that already holds one, fails with a `400`.
The error carries the code `VALIDATION_ERROR`, and its item names the `sub_channels` field with the code `INVALID_VALUE`.
* **`updated_at` orders the writes.**
Mirakl Connect ignores an addition, an update, or a removal whose `updated_at` is older than the value it already holds for that sub-channel.
This is the same anti-replay guard as `channel_updated_at` on an order.
* **The currency is set once.**
Mirakl Connect stores a sub-channel's `currency` the first time it receives it, and it keeps that value.
A later call that carries a different currency succeeds and changes nothing.
* **There is no read-back.**
No Channel Platform operation returns a store's sub-channels, so your connector holds the list it sent.


Adding a sub-channel makes Mirakl Connect synchronize the store's catalog for it.
Expect a price and stock event for every offer of the store.

Removing a sub-channel stops the offer synchronization for the sales channel it names.
Remove one only once the seller no longer sells on it.

## Linking stores in Mirakl Connect

Once the channel configuration is complete and the stores are imported from the channel into Mirakl Connect, the seller can link a store and activate the product and order flows.
Your connector must implement the following workflow to link the selected store.

```mermaid
sequenceDiagram
    autonumber
    box rgb(254,226,226) Seller
    actor SE as Seller
    end
    box rgb(219,234,254) Mirakl
    participant MC as Mirakl Connect
    participant MA as Mirakl Account
    end
    box rgb(209,250,229) Middleware
    participant CN as Channel Connector
    end
    box rgb(254,240,199) Channel
    participant CH as Channel
    end

    SE->>MA: Select a channel store and link it
    MA--)MC: Store linked
    MC--)CN: StoreManagementFeatureEvent (store-linking, status "linked")
    CN->>CH: Fetch the store's detailed information
    CN->>MC: upsertBusinessInformation
    CN->>CN: Activate the store synchronization flows
```

Follow these steps:

* **Step 1:** the seller selects a channel store and links it, and Mirakl Account records the link.
* **Step 2:** Mirakl Account notifies Mirakl Connect that the store is linked.
* **Step 3:** Mirakl Connect triggers a [StoreManagementFeatureEvent](/content/product/connect-channel-platform/webhooks/webhook/webhooks/storemanagementfeatureevent) and sends it to the connector, with the store's basic information.
The connector consumes this event, checks that `feature` is `store-linking`, then reads the status in the configuration.
The steps below apply when the value is `linked`.
For more information, refer to the [Event APIs reference](/content/product/connect-channel-platform/webhooks/webhook).
* **Step 4:** the connector fetches the store's detailed information from the channel.
* **Step 5:** the connector upserts that information in Mirakl Connect, with the [upsertBusinessInformation](/content/product/connect-channel-platform/rest/connect/openapi3/store/upsertbusinessinformation) API.
For more information, refer to the [REST APIs reference](/content/product/connect-channel-platform/rest/connect/openapi3).
* **Step 6:** the connector activates the store synchronization flows.


## Unlinking stores in Mirakl Connect

A seller can unlink a store in Mirakl Connect.
In this case, your connector must implement the following workflow to deactivate the store synchronization flows.

```mermaid
sequenceDiagram
    autonumber
    box rgb(254,226,226) Seller
    actor SE as Seller
    end
    box rgb(219,234,254) Mirakl
    participant MC as Mirakl Connect
    participant MA as Mirakl Account
    end
    box rgb(209,250,229) Middleware
    participant CN as Channel Connector
    end

    SE->>MA: Unlink a channel store
    MA--)MC: Store unlinked
    MC--)CN: StoreManagementFeatureEvent (store-linking, status "unlinked")
    CN->>CN: Deactivate the store synchronization flows
```

Mirakl and the connector settle the unlinking between them.
Nothing is sent to the channel.

Follow these steps:

* **Step 1:** the seller unlinks a channel store, and Mirakl Account records the unlinking.
* **Step 2:** Mirakl Account notifies Mirakl Connect that the store is unlinked.
* **Step 3:** Mirakl Connect triggers a [StoreManagementFeatureEvent](/content/product/connect-channel-platform/webhooks/webhook/webhooks/storemanagementfeatureevent) and sends it to the connector, with the store's basic information.
The connector consumes this event, checks that `feature` is `store-linking`, then reads the status in the configuration.
The step below applies when the value is `unlinked`.
For more information, refer to the [Event APIs reference](/content/product/connect-channel-platform/webhooks/webhook).
* **Step 4:** the connector deactivates the store synchronization flows.


## Related pages

* [Channel authorization](/content/product/connect-channel-platform/developer-guide/channel-authorization): the process that obtains the seller's consent and creates their stores.
* [Business use cases](/content/product/connect-channel-platform/developer-guide/business-use-cases): where the store flows sit among the flows you implement.
* [Catalog configuration](/content/product/connect-channel-platform/developer-guide/catalog-configuration): the lifecycle that decides whether each sub-channel of a store gets its own prices and stock.
* [Data model](/content/product/connect-channel-platform/getting-started/data-model): the store and the entities that hang off it, defined field by field.
* [Receiving events](/content/product/connect-channel-platform/developer-guide/receiving-events): how the link and unlink events above reach your connector.