> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rxscale.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Products

> List products for a shop via the Public API

# Products

Retrieve a paginated list of products available in a specific shop, filtered by market.

## List Products

```bash theme={null}
GET /v2/public-api/products/{shop_identifier}
```

<ParamField path="shop_identifier" type="string" required>
  Unique identifier for the shop
</ParamField>

<ParamField query="market" type="string" required>
  Market identifier (e.g. `DE` for Germany)
</ParamField>

<ParamField query="search" type="string">
  Filter products and SKUs by name
</ParamField>

<ParamField query="page" type="integer" default="0">
  Page number (0-indexed)
</ParamField>

<ParamField query="limit" type="integer" default="50">
  Results per page (max 150)
</ParamField>

**Required permission:** `product:read`

### Example Request

```bash theme={null}
curl -X GET "https://api.rxscale.com/v2/public-api/products/my-shop?market=DE&page=0&limit=25" \
  -H "X-API-Key: your-api-key-here"
```

### Response

```json theme={null}
{
  "data": [
    {
      "uid": "prod-abc123",
      "display_name": "Medication X",
      "attributes": {
        "category": "Pain Relief"
      },
      "skus": [
        {
          "uid": "sku-456",
          "display_name": "Medication X 100mg",
          "attributes": {
            "package_size": "100mg"
          },
          "availability": "High",
          "telemedicine_provider_data": {
            "external_id": "partner-sku-456"
          },
          "price": 1299,
          "currency": "EUR",
          "unit": "g",
          "standard_selling_unit": 10
        },
        {
          "uid": "sku-789",
          "display_name": "Medication X 200mg",
          "attributes": {
            "package_size": "200mg"
          },
          "availability": "Medium",
          "telemedicine_provider_data": {
            "external_id": "partner-sku-789"
          },
          "price": 1999,
          "currency": "EUR",
          "unit": "g",
          "standard_selling_unit": 20
        }
      ]
    }
  ],
  "totalRegistries": 42,
  "totalPages": 2
}
```

### Response Fields

| Field                                                  | Type    | Description                                                     |
| ------------------------------------------------------ | ------- | --------------------------------------------------------------- |
| `data`                                                 | array   | List of product objects                                         |
| `data[].uid`                                           | string  | Product UID                                                     |
| `data[].display_name`                                  | string  | Product display name                                            |
| `data[].attributes`                                    | object  | Product attributes as key-value pairs                           |
| `data[].skus`                                          | array   | Available SKUs for this product in the given market             |
| `data[].skus[].uid`                                    | string  | SKU UID (use this when creating checkouts)                      |
| `data[].skus[].display_name`                           | string  | SKU display name                                                |
| `data[].skus[].attributes`                             | object  | SKU attributes as key-value pairs                               |
| `data[].skus[].availability`                           | string  | Availability bucket (`High`, `Medium`, `Low`, or `Unavailable`) |
| `data[].skus[].telemedicine_provider_data.external_id` | string  | External SKU identifier for the telemedicine provider           |
| `data[].skus[].price`                                  | integer | Price in euro cents                                             |
| `data[].skus[].currency`                               | string  | Price currency                                                  |
| `data[].skus[].unit`                                   | string  | SKU unit                                                        |
| `data[].skus[].standard_selling_unit`                  | number  | Standard selling unit                                           |
| `totalRegistries`                                      | integer | Total number of matching products                               |
| `totalPages`                                           | integer | Total number of pages                                           |

### Error Responses

| Status Code | Description                      |
| ----------- | -------------------------------- |
| `400`       | Missing `market` query parameter |
| `404`       | Shop not found                   |

## Check Live Stock

Check whether one or more SKUs are currently available in the requested quantities before the checkout starts.

```bash theme={null}
POST /v2/public-api/products/{shop_identifier}/live-stock
```

<ParamField path="shop_identifier" type="string" required>
  Unique identifier for the shop
</ParamField>

**Required permission:** `product:read`

<Note>
  Live stock is checked against Shopify's current available inventory for the mapped product variants. This includes inventory already held by Shopify orders and draft-order reservations.
</Note>

### Request Body

```json theme={null}
[
  {
    "sku_uid": "sku-456",
    "quantity": 2
  },
  {
    "sku_uid": "sku-789",
    "quantity": 1
  }
]
```

| Field      | Type    | Required | Description                             |
| ---------- | ------- | -------- | --------------------------------------- |
| `sku_uid`  | string  | Yes      | SKU UID from the product catalog        |
| `quantity` | integer | Yes      | Quantity to check. Must be at least `1` |

Each `sku_uid` can appear only once per live stock request.

### Example Request

```bash theme={null}
curl -X POST "https://api.rxscale.com/v2/public-api/products/my-shop/live-stock" \
  -H "X-API-Key: your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "sku_uid": "sku-456",
      "quantity": 2
    }
  ]'
```

### Available Response

When all requested quantities are available, the endpoint returns `200 OK`.

```json theme={null}
{
  "available": true,
  "lines": [
    {
      "sku_uid": "sku-456",
      "quantity": 2,
      "available": true,
      "available_stock": 12
    }
  ]
}
```

### Unavailable Response

When at least one requested quantity is not available, the endpoint returns `409 Conflict`.

```json theme={null}
{
  "available": false,
  "lines": [
    {
      "sku_uid": "sku-456",
      "quantity": 2,
      "available": false,
      "available_stock": 1
    }
  ]
}
```

### Response Fields

| Field                     | Type    | Description                                             |
| ------------------------- | ------- | ------------------------------------------------------- |
| `available`               | boolean | `true` only when all requested quantities are available |
| `lines[].sku_uid`         | string  | Requested SKU UID                                       |
| `lines[].quantity`        | integer | Requested quantity                                      |
| `lines[].available`       | boolean | Whether this SKU has enough stock                       |
| `lines[].available_stock` | integer | Current stock available for the SKU in the shop         |

### Error Responses

| Status Code | Description                                          |
| ----------- | ---------------------------------------------------- |
| `400`       | Body validation failed or duplicate `sku_uid` values |
| `404`       | Shop or SKU not found                                |
| `409`       | At least one requested quantity is unavailable       |

## Reserve Products

Create a Shopify draft order with a 24-hour inventory reservation before prescriptions are available. Use the returned draft order ID later as `reserved_draft_order_id` when uploading signed prescriptions.

```bash theme={null}
POST /v2/public-api/products/{shop_identifier}/reservation
```

<ParamField path="shop_identifier" type="string" required>
  Unique identifier for the shop
</ParamField>

**Required permission:** `create_prescription_checkout`

<Note>
  The reservation request does not include prescriptions or patient data. RxScale adds telemedicine provider attributes from the API key automatically.
</Note>

<Warning>
  The API key must be linked to a telemedicine provider. Requests with a non-telemedicine API key are rejected with `400 Bad Request` before any inventory is held, because the resulting draft order could not be matched on the later prescription upload.
</Warning>

### Request Body

```json theme={null}
{
  "external_reservation_id": "caller-reservation-123",
  "lines": [
    {
      "sku_uid": "sku-456",
      "quantity": 1
    }
  ]
}
```

| Field                     | Type    | Required | Description                                                                                 |
| ------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------- |
| `external_reservation_id` | string  | No       | Your reservation identifier. Stored on the Shopify draft order and returned in the response |
| `lines`                   | array   | Yes      | Products to reserve                                                                         |
| `lines[].sku_uid`         | string  | Yes      | SKU UID from the product catalog                                                            |
| `lines[].quantity`        | integer | Yes      | Quantity to reserve                                                                         |

Each `sku_uid` can appear only once per reservation request. Duplicate SKU lines are rejected because the later prescription upload must match each reserved draft-order line unambiguously.

### Example Request

```bash theme={null}
curl -X POST "https://api.rxscale.com/v2/public-api/products/my-shop/reservation" \
  -H "X-API-Key: your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "external_reservation_id": "caller-reservation-123",
    "lines": [
      {
        "sku_uid": "sku-456",
        "quantity": 1
      }
    ]
  }'
```

### Response

```json theme={null}
{
  "status": "success",
  "external_reservation_id": "caller-reservation-123",
  "draft_order": {
    "id": "123",
    "invoiceUrl": "https://example.myshopify.com/invoice/...",
    "reserve_inventory_until": "2026-05-16T17:20:00Z"
  }
}
```

The `draft_order.id` is the Shopify legacy DraftOrder ID, not the Shopify GID. Pass this value to `POST /v2/public-api/prescriptions/{shop_identifier}` as `reserved_draft_order_id` after the prescriptions are signed.

### Error Responses

| Status Code | Description                                                                                             |
| ----------- | ------------------------------------------------------------------------------------------------------- |
| `400`       | API key is not linked to a telemedicine provider, body validation failed, or duplicate `sku_uid` values |
| `404`       | Shop or SKU not found                                                                                   |
