> For the complete documentation index, see [llms.txt](https://docs.hello-lisa.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hello-lisa.com/developers/guides/player-communication/message-api-reference/products/products-hydrate.md).

# Products — Hydrate

The host app or environment sends a **Hydrate** message to give the LiSA Player current price and availability for products the player already knows about.

Send it in reply to a Products — Request Hydration message. The player merges what you send onto the product data the show was authored with, and re-renders any product already on screen.

{% hint style="warning" %}
Await the App — Listen message before sending. Messages sent earlier may not reach the player.
{% endhint %}

### Properties

Along with all standard [Message properties](/developers/guides/player-communication/message-api-reference.md#properties), a **Hydrate** message includes the following additional properties:

<table><thead><tr><th width="243" valign="top">Name</th><th width="192" valign="top">Type</th><th valign="top">Description</th></tr></thead><tbody><tr><td valign="top"><code>messageType</code></td><td valign="top"><pre><code>Literal
</code></pre><p>Required.</p></td><td valign="top"><code>lsc:products:hydrate</code></td></tr><tr><td valign="top"><code>products</code></td><td valign="top"><pre><code>Array&#x3C;HydratedProduct>
</code></pre><p>Required.</p></td><td valign="top">The refreshed products.<br><br>References the player does not recognize are ignored, and products you leave out keep their authored values — so it is safe to answer with a partial set, or with more products than were asked for.<br><br>Refer to <a href="#hydratedproduct"><code>HydratedProduct</code></a> for detailed information.</td></tr></tbody></table>

### Merge rules

Two rules govern how the player applies what you send. Both exist so that a partial answer is always safe.

1. **Anything you omit keeps its authored value.** A message carrying only `hasStock` will never blank out a title, image, brand or variant. You never have to reconstruct the full product.
2. **Supplying `price` replaces both `price` and `salePrice`.** This is how a product coming off sale is expressed: send the price object without a `salePrice`. If you want to leave pricing untouched, omit `price` entirely.

***

### Type Definition

```typescript
interface ProductsHydrateMessage extends Omit<Message, 'messageType'> {
  messageType: 'lsc:products:hydrate';
  products: Array<HydratedProduct>;
  recipient: 'LiSA';
}
```

#### **HydratedProduct**

Fresh state for one product. Only the attributes that go stale are carried.

<table><thead><tr><th width="243" valign="top">Name</th><th width="192" valign="top">Type</th><th valign="top">Description</th></tr></thead><tbody><tr><td valign="top"><code>hasStock</code></td><td valign="top"><pre><code>Boolean
</code></pre><p>Optional.</p></td><td valign="top">Whether the product can currently be bought. The player uses this to render its sold-out state and to enable or disable the add-to-cart call-to-action.</td></tr><tr><td valign="top"><code>price</code></td><td valign="top"><pre><code>HydratedProductPrice
</code></pre><p>Optional.</p></td><td valign="top">The current pricing. Supplying it replaces both <code>price</code> and <code>salePrice</code>.<br><br>Refer to <code>HydratedProductPrice</code> for detailed information.</td></tr><tr><td valign="top"><code>reference</code></td><td valign="top"><pre><code>String
</code></pre><p>Required.</p></td><td valign="top">The merchant's own product identifier, as supplied to LiSA when the product was created. This is the key the player matches on.</td></tr><tr><td valign="top"><code>variants</code></td><td valign="top"><pre><code>Array&#x3C;HydratedProductVariant>
</code></pre><p>Optional.</p></td><td valign="top">Per-variant state, for products sold in sizes, colors or other variations.<br><br>Variants you leave out keep their authored values.</td></tr></tbody></table>

#### **HydratedProductVariant**

<table><thead><tr><th width="243" valign="top">Name</th><th width="192" valign="top">Type</th><th valign="top">Description</th></tr></thead><tbody><tr><td valign="top"><code>hasStock</code></td><td valign="top"><pre><code>Boolean
</code></pre><p>Optional.</p></td><td valign="top">Whether this variant can currently be bought.</td></tr><tr><td valign="top"><code>price</code></td><td valign="top"><pre><code>HydratedProductPrice
</code></pre><p>Optional.</p></td><td valign="top">Pricing for this variant, when it differs from the product's.</td></tr><tr><td valign="top"><code>reference</code></td><td valign="top"><pre><code>String
</code></pre><p>Required.</p></td><td valign="top">The merchant's own variant identifier.</td></tr></tbody></table>

#### **HydratedProductPrice**

<table><thead><tr><th width="243" valign="top">Name</th><th width="192" valign="top">Type</th><th valign="top">Description</th></tr></thead><tbody><tr><td valign="top"><code>currencyCode</code></td><td valign="top"><pre><code>String
</code></pre><p>Required.</p></td><td valign="top">The ISO 4217 currency code, for example <code>EUR</code>.</td></tr><tr><td valign="top"><code>currencySymbol</code></td><td valign="top"><pre><code>String
</code></pre><p>Optional.</p></td><td valign="top">The symbol to render, for example <code>€</code>.<br><br>When omitted, the player keeps the symbol the product was authored with, and falls back to <code>currencyCode</code> if the product had no price at all.</td></tr><tr><td valign="top"><code>price</code></td><td valign="top"><pre><code>Number
</code></pre><p>Required.</p></td><td valign="top">The undiscounted price.</td></tr><tr><td valign="top"><code>salePrice</code></td><td valign="top"><pre><code>Number
</code></pre><p>Optional.</p></td><td valign="top">The discounted price, when the product is on sale. Omit it to express that the product is no longer on sale.</td></tr></tbody></table>

```typescript
interface HydratedProduct {
  hasStock?: boolean;
  price?: HydratedProductPrice;
  reference: string;
  variants?: Array<HydratedProductVariant>;
}

interface HydratedProductVariant {
  hasStock?: boolean;
  price?: HydratedProductPrice;
  reference: string;
}

interface HydratedProductPrice {
  currencyCode: string;
  currencySymbol?: string;
  price: number;
  salePrice?: number;
}
```

### Example

A product on sale with one sold-out variant, and a second product that sold out entirely:

```json
{
  "messageType": "lsc:products:hydrate",
  "recipient": "LiSA",
  "sender": "my-shop",
  "messageId": "b8c9d0e1-f2a3-4b4c-8d5e-7f8091a2b3c4",
  "products": [
    {
      "reference": "SKU-1234",
      "hasStock": true,
      "price": {
        "currencyCode": "EUR",
        "currencySymbol": "€",
        "price": 69.9,
        "salePrice": 49.9
      },
      "variants": [
        { "reference": "SKU-1234-S", "hasStock": false },
        { "reference": "SKU-1234-M", "hasStock": true }
      ]
    },
    {
      "reference": "SKU-5678",
      "hasStock": false
    }
  ]
}
```
