---
title: "On Demand Data"
canonical: "https://red-ant-documentation.refined.site/space/RDD/632127591/On%20Demand%20Data"
format: markdown
---
> Macro (toc)

# Summary

Welcome to our web service documentation for RetailOS. This document aims to guide you through an approach commonly used to integrate your retail or e-commerce systems with RetailOS to **fetch data on demand. **The diagram below represents the components involved when RetailOS is configured to use an on-demand integration.

Throughout the document, we will delve deeper into the types of on-demand integrations supported, providing detailed examples, configuration guidelines, and best practices to help you implement them effectively.

![Simplified On-Demand Architecture Diagram v1.0.png](media://bdeadcc7-6be6-4232-8ef6-ad05b5709da8)

# Architecture Overview

RetailOS V2 API introduces a concept known as "API Hooks". This allows for customizations of API endpoints per client. The underlying concept is that an endpoint is built with the custom logic and configured to be used with RetailOS V2. There are two ways of using API hooks:

- **"replace":** This is used to replace all functionality for an endpoint with custom behavior
- **"after":** This is used to manipulate an endpoint's response with custom logic

## Replace API Hooks

API hooks can be set up to "replace" V2 endpoints. This will proxy requests to a configured HTTP(s) endpoint, ignoring all default RetailOS API logic. This allows developers to implement completely custom logic per endpoint.


![v2_api_hooks_replace.jpg](media://5b59db5a-5a65-4960-95b6-b25c6c5c3342)


## After API Hooks

API hooks can be set up to run "after" V2 endpoints. This will run the normal RetailOS V2 controller logic, but before responding to the caller, it will send the response to the configured HTTP(s) endpoint. This allows developers to modify the response data before it is sent back to the client.

![v2_api_hooks_after.jpg](media://795440c3-8269-4bb9-b965-e459db882d80)


# Bypass

Api hooks can be bypassed if the user passes `ignoreApiHooks=true` to the request query parameters.

Example URL

```
GET http://localhost:8080/v2/customers?ignoreApiHooks=trueCopy to clipboardErrorCopied
```

This will ignore any API hook configuration for the specific route. It can be useful where a `replace` hook needs to invoke the RetailOS controller.

---

## Authentication and security

- **API Key**: An API key can be passed as part of the request headers to authenticate the request from RetailOS to external systems

---

## API hook implementation

The following are assumed expectations of any web services RetailOS interacts with

### Content type

RetailOS will send JSON data in all of its requests and expect JSON format in response. The following request headers will be sent:

```
Content-Type: application/json
Accept: application/jsonCopy to clipboardErrorCopied
```

### HTTP request body

RetailOS will send JSON data with two object properties:

- **incomingRequest** Parsed HTTP requst received by the RetailOS API
- **controllerResponse** Object containing the response information from RetailOS. Only valid for `hookType=after`, otherwise `null`.

#### IncomingRequest object

RetailOS will parse the HTTP request from the app and forward an *IncomingRequest* object to your API as part of the request body. The object will have the following data:

- **routePath** Internal router path with tokens as placeholders for request params
- **requestPath** Full incoming request path
- **requestMethod** HTTP request method
- **body** HTTP JSON parsed request body
- **params** Request URL parameters
- **query** Request URL query parameters
- **headers** Request headers
- **queryContext** Parsed request query parameters
- **auth** Request user authentication data
- **meta** Request metadata
- **meta.requestId** Incoming request trace id
- **meta.requestTimestamp** Incoming request timestamp

<details>
<summary>Example IncomingRequest object</summary>

```json
{
    "routePath": "/customers/:id",
    "requestPath": "/customers/7538051",
    "requestMethod": "GET",
    "body": {},
    "params": {
      "id": "7538051"
    },
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

#### ControllerResponse object (successful)

RetailOS will send the response information as part of the request body under the property `controllerResponse`. This is only used for `after` hooks, otherwise, the value of this property will be `null`.

The object will have the following data (in case of successful requests):

- **isControllerResponse** Used internally to identify controller responses
- **message** Success message
- **statusCode** HTTP response status code
- **result** Controller result

<details>
<summary>Example ControllerResponse object</summary>

```json
{
  "isControllerResponse": true,
  "message": "Customer",
  "statusCode": 200,
  "result": {
    "id": "58c244ce-20bd-4e6c-ad5d-3aa5c0736660",
    "updateSource": null,
    "externalCustomerId": "753805",
    "title": "Mrs.",
    "gender": null,
    "firstName": "John",
    "lastName": "Doe",
    "telephone": null,
    "email": "john.doe@test.com",
    "dob": null,
    "generalMarketing": false,
    "thirdPartyMarketing": false,
    "storeMarketing": false,
    "smsMarketing": false,
    "emailMarketing": false,
    "postMarketing": false,
    "address": null,
    "details": {},
    "reporting": {},
    "anonymised": false,
    "notes": null,
    "createdAt": "2020-01-03T13:32:50.381Z",
    "updatedAt": "2020-02-20T13:19:01.006Z",
    "deletedAt": null,
    "registeredById": null,
    "registeredAtId": null,
    "territoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1"
  },
  "meta": {}
}
```
</details>

#### ControllerResponse object (exceptions)

RetailOS will send the response information as part of the request body under the property `controllerResponse`. This is only used for `after` hooks, otherwise the value of this property will be `null`.

The object will have the following data (in case of failed requests):

- **isControllerException** Used internally to identify controller responses
- **code** Error code
- **message** Error message
- **statusCode** HTTP response status code
- **details** details object

<details>
<summary>Example ControllerResponse object</summary>

```json
{
  "message": "Customer not found.",
  "stack": "Error: Customer not found.\n    at RestController.getOne (/Users/abrarm/redant/libraries/retailos-js/build/main/modules/resources/abstract/abstract.controller.js:60:23)\n    at <anonymous>",
  "isControllerException": true,
  "code": "CUSTOMER_NOT_FOUND",
  "statusCode": 404,
  "details": {}
}
```
</details>

### HTTP response status codes

The response status code will be forwarded as the response to the user of the API.

### HTTP response body

RetailOS expects a JSON response with at least an `error` or `result` property. See below.

#### Successful responses

In the case of a successful response, the body should contain the `result` property and match that of the resources' SwaggerUI successful response schema

<details>
<summary>Example</summary>

```json
{
  "error": null,
  "result": {
    "id": "58c244ce-20bd-4e6c-ad5d-3aa5c0736660",
    "updateSource": null,
    "externalCustomerId": "753805",
    "title": "Mrs.",
    "gender": null,
    "firstName": "John",
    "lastName": "Doe",
    "telephone": null,
    "email": "john.doe@test.com",
    "dob": null,
    "generalMarketing": false,
    "thirdPartyMarketing": false,
    "storeMarketing": false,
    "smsMarketing": false,
    "emailMarketing": false,
    "postMarketing": false,
    "address": null,
    "details": {},
    "reporting": {},
    "anonymised": false,
    "notes": null,
    "createdAt": "2020-01-03T13:32:50.381Z",
    "updatedAt": "2020-02-20T13:19:01.006Z",
    "deletedAt": null,
    "registeredById": null,
    "registeredAtId": null,
    "territoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1"
  }
}
```
</details>

#### Error responses

In the case of an error response, the body should contain the `error` object as shown below, and be similar to that of the resources' errors.

<details>
<summary>Example</summary>

```json
{
  "error": {
    "code": "CUSTOMER_NOT_FOUND",
    "message": "Customer not found",
    "details": null
  },
  "result": null
}
```
</details>

# Working with RetailOS data schemas

## Example Requests

## Categories

[https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/718766103](https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/718766103) 

<details>
<summary>Request</summary>

```json
{
    "routePath": "/categories",
    "requestPath": "/categories",
    "requestMethod": "GET",
    "body": {},
    "params": {},
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

<details>
<summary>Response</summary>

```json
{
  "error": null,
  "result": [
    {
      "id": "440c4c8d-301f-4fdb-a4b9-7af103798574",
      "updateSource": null,
      "externalCategoryId": "hoodies",
      "name": "Hoodies",
      "image": "",
      "order": 1,
      "parentId": "d83b47c6-c7ce-4964-8160-9910a65c766d"
    }
  ]
}
```
</details>

## Products

[https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/717520906](https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/717520906) 

<details>
<summary>Request</summary>

```
{
    "routePath": "/products",
    "requestPath": "/products",
    "requestMethod": "GET",
    "body": {},
    "params": {},
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

<details>
<summary>Response</summary>

```json
{
  "error": null,
  "result": [
      {
        "id": "3b944e16-b15f-4d7c-9d59-ba9fde852dd4",
        "externalProductId": "cd534545f58e8ef9511965e57733d15a",
        "updateSource": null,
        "name": "Gucci Flora Gorgeous Gardenia Eau de Parfum 30ml Giftset",
        "catalogue": "retailos-beauty",
        "secondaryName": null,
        "link": null,
        "brand": "Gucci",
        "vatPercent": null,
        "promotionalText": null,
        "price": {
          "code": "GBP",
          "value": "102"
        },
        "discount": {
          "code": "GBP",
          "value": "0"
        },
        "images": [
          "https://media.gucci.com/style/DarkGray_Center_0_0_800x800/1634220011/689949_99999_0099_002_100_0000_Light-Gucci-Flora-Gorgeous-Gardenia-gift-set.jpg"
        ],
        "embeddedVideos": [],
        "videoThumbnails": null,
        "details": {
          "summary": "Gucci Flora Gorgeous Gardenia Eau de Parfum for Women is a joyful floral perfume.\nA delicious potion of joy built around the Gardenia flower blended with solar Jasmine absolute, cheerful Pear Blossom accord and sweet Brown Sugar accord.",
          "description": "GUCCI FL GG EDP 30ml Giftset",
          "searchTerms": [
            "Gucci|Gucci Flora|Gorgeous Gardenia|Flora Eau de Parfum|Flora by Gucci|Gucci Fragrances|Perfume|perfect gift|Floral|Perfect Gift for her|for women|Fruity|Fresh"
          ],
          "productSizeGuide": "30 ML",
          "productCareInstructions": "Daily use.|Layer over the skin, applying delicately to the wrist, neck and chest."
        },
        "reporting": {},
        "preview": false,
        "service": false,
        "storeroomOnly": false,
        "clientId": null,
        "productGroup": "Gorgeous Gardenia",
        "createdAt": "2024-02-09T13:23:05.428Z",
        "updatedAt": "2024-02-09T13:23:05.428Z",
        "deletedAt": null,
        "categoryId": "13e6563c-18ee-4ee6-837c-16718334a6ed",
        "regionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc"
      }
  ]
}
```
</details>

## Variants

[https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/719486985](https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/719486985) 

<details>
<summary>Request</summary>

```
{
    "routePath": "/variants",
    "requestPath": "/variants",
    "requestMethod": "GET",
    "body": {},
    "params": {},
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

<details>
<summary>Response</summary>

```json
{
  "error": null,
  "result": [
      {
        "id": "957dc4a7-16bd-4e12-9599-6be98d7f3ed2",
        "updateSource": null,
        "externalVariantId": "3616304679018",
        "name": "Gucci Flora Gorgeous Gardenia Eau de Parfum 30ml Giftset",
        "link": null,
        "variantOrder": 3,
        "ean": "3616304679018",
        "details": {},
        "onlineStock": "available",
        "catalogue": "retailos-beauty",
        "price": {
          "code": "GBP",
          "value": "102"
        },
        "discount": {
          "code": "GBP",
          "value": "0"
        },
        "createdAt": "2024-02-09T13:24:32.366Z",
        "updatedAt": "2024-02-09T13:24:32.366Z",
        "deletedAt": null,
        "productId": "3b944e16-b15f-4d7c-9d59-ba9fde852dd4",
        "regionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc"
      }
  ]
}
```
</details>

## Store Stock

[https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/719126586](https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/719126586) 

<details>
<summary>Request</summary>

```
{
    "routePath": "/stocks",
    "requestPath": "/stocks",
    "requestMethod": "GET",
    "body": {},
    "params": {},
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

<details>
<summary>Response</summary>

```json
{
  "error": null,
  "result": [
      {
        "storeId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8",
        "variantId": "435a5bbe-5f46-470e-9599-53062cd70205",
        "updateSource": null,
        "stock": 7,
        "details": {},
        "createdAt": "2024-02-08T12:14:35.802Z",
        "updatedAt": "2024-02-08T12:14:35.802Z",
        "deletedAt": null
      }
  ]
}
```
</details>

## Orders

[https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/761921553](https://redantdigital.atlassian.net/wiki/spaces/RDD/pages/761921553) 

<details>
<summary>Request</summary>

```json
{
    "routePath": "/orders",
    "requestPath": "/orders",
    "requestMethod": "GET",
    "body": {},
    "params": {},
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

<details>
<summary>Response</summary>

```json
{
  "error": null,
  "result": [
      {
        "id": "0be510c3-edba-40bf-9e79-f674d7d478fa",
        "tax": {
          "code": "GBP",
          "value": 0
        },
        "total": {
          "code": "GBP",
          "value": 0
        },
        "subTotal": {
          "code": "GBP",
          "value": 59
        },
        "totalDiscount": {
          "code": "GBP",
          "value": 59
        },
        "status": "complete",
        "orderNumber": "9098-917246-0902",
        "updateSource": "RetailOS",
        "externalOrderId": null,
        "salesChannel": "Store",
        "orderDate": "2024-04-15T12:36:00.649Z",
        "products": [
          {
            "id": "d65c7af7-93b2-46a1-a62e-a303704754b9",
            "tax": {
              "code": "GBP",
              "value": 0
            },
            "link": "https://www.selfridges.com/GB/en/cat/yves-saint-laurent-pure-shots-perfect-plumper-cream-50ml_R00102327/",
            "name": "Pure Shots Perfect Plumper cream",
            "brand": "Yves Saint Laurent",
            "price": {
              "code": "GBP",
              "value": 59
            },
            "total": {
              "code": "GBP",
              "value": 0
            },
            "images": [
              "https://images.selfridges.com/is/image/selfridges/R00102327_ALT10?$PDP_M_ZOOM$&defaultImage=R00102327_M"
            ],
            "unsold": false,
            "isLoved": false,
            "preview": false,
            "service": false,
            "variant": {
              "id": "e1689eb0-6eca-4547-a477-b2f1b3674f7d",
              "ean": "4599487612364",
              "name": "One Size",
              "details": {
                "variantId": "504074"
              }
            },
            "clientId": null,
            "discount": {
              "code": "GBP",
              "value": 0
            },
            "subTotal": {
              "code": "GBP",
              "value": 0
            },
            "productId": "e71f6264-2785-432c-b639-6898ec39446e",
            "categoryId": "9cb6b6b8-768e-40db-bf41-adfe2f478520",
            "vatPercent": null,
            "manualDiscount": {
              "code": "GBP",
              "value": 59
            },
            "priceAdjustments": [
              {
                "type": "MANUAL_DISCOUNT",
                "result": {
                  "code": "GBP",
                  "value": 0
                },
                "createdAt": "2024-04-15T12:35:56.833Z",
                "appliedDiscount": {
                  "type": "percentage",
                  "percentage": "100"
                }
              }
            ],
            "externalProductId": "866423"
          }
        ],
        "orderType": "standard",
        "paymentToken": null,
        "deliveryType": "store",
        "deliveryOption": {
          "id": "fa25a11b-1848-4f0f-a8d3-8d4756e99243",
          "name": "Standard Delivery",
          "price": {
            "code": "GBP",
            "value": 0
          },
          "active": true,
          "details": null,
          "deliveryType": "store"
        },
        "deliveryAddress": {
          "city": "Edinburgh",
          "address1": "Absolutely Gorgeous Boutique",
          "lastName": "Customer",
          "firstName": "Example"
        },
        "deliveryDetails": null,
        "details": {
          "payment": {
            "completed": true,
            "paymentIntent": null,
            "paymentMethod": {
              "id": "SKIP_PAYMENT",
              "label": "Skip Payment",
              "checkoutType": [
                "inStoreConsultation",
                "basketCheckout"
              ]
            }
          }
        },
        "returningCustomer": true,
        "previousOrderId": null,
        "orderPriceAdjustments": [],
        "createdAt": "2024-04-15T12:36:00.721Z",
        "updatedAt": "2024-04-15T12:36:02.884Z",
        "deletedAt": null,
        "customerId": "b18f8abb-3e43-468f-bb58-e38a0a5e636a",
        "storeId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8",
        "userId": "2cc26e43-102e-469b-81fc-a2d816915245",
        "createdByUserId": "2cc26e43-102e-469b-81fc-a2d816915245"
      }
  ]
}
```
</details>

## Customers

Customer Schema (not created yet)

<details>
<summary>Request</summary>

```json
{
    "routePath": "/customers",
    "requestPath": "/customers",
    "requestMethod": "GET",
    "body": {},
    "params": {},
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "accept": "application/json",
      "authorization": "Bearer <bearer auth token>",
      "user-agent": "...",
      "accept-language": "en-US,en;q=0.9",
      "cookie": "..."
    },
    "query": {},
    "queryContext": {
      "filter": {},
      "pagination": {
        "offset": 0,
        "limit": 50
      },
      "sort": {
        "direction": "DESC",
        "field": "updatedAt"
      },
      "fields": [],
      "includes": []
    },
    "meta": {
      "requestId": "fd1063f6-f59a-472d-a6d3-7907652f0ff9",
      "requestTimestamp": "2020-07-08T10:00:29.748Z",
      "serverVersion": "2.288.0"
    },
    "auth": {
      "user": {
        "catalogue": "example-poroduct-catalogue",
        "currentRegionFeatures": {},
        "currentRegionId": "580d3be5-e90b-46ce-8bc5-04e9f0ae13cc",
        "currentTerritoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1",
        "currencyCode": "GBP",
        "id": "978a7d05-080d-4af1-8bce-ebc4340bf5cc",
        "username": "john.doe",
        "email": "john.doe@example.com",
        "firstName": "John",
        "lastName": "Doe",
        "gender": "Male",
        "dob": null,
        "telephone": null,
        "currentDepartmentId": "35d091a5-312c-46e7-bff0-785f43897a81",
        "currentStoreId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8"
      },
      "role": {
        "id": "704894fb-cb1b-4ff0-8c58-b394696ac40f",
        "name": "Admin",
        "value": 1,
        "isAdmin": true,
        "multipleStores": true,
        "permissions": {...}
      },
      "stores": [],
      "type": "USER",
      "iat": 1589462040,
      "exp": 1653462040,
      "iss": "DIGITAL_STORE",
      "sub": "978a7d05-080d-4af1-8bce-ebc4340bf5cc"
    }
}
```
</details>

<details>
<summary>Response</summary>

```json
{
  "error": null,
  "result": [
      {
        "id": "f26407da-72d8-47a0-b2b6-14e783b86af9",
        "updateSource": "RetailOS",
        "externalCustomerId": null,
        "title": "Anonymised",
        "gender": "Anonymised",
        "firstName": "Anonymised",
        "lastName": "Anonymised",
        "telephone": "Anonymised",
        "email": "72d33d7e-b34f-4e24-959c-e25a860e0f51@anon.com",
        "dob": "Anonymised",
        "generalMarketing": null,
        "thirdPartyMarketing": false,
        "storeMarketing": false,
        "smsMarketing": false,
        "whatsappMarketing": false,
        "registrationSource": null,
        "emailMarketing": false,
        "postMarketing": false,
        "address": {},
        "details": {},
        "reporting": {},
        "anonymised": true,
        "notes": [],
        "createdAt": "2023-10-05T00:29:03.400Z",
        "updatedAt": "2023-10-05T00:29:09.057Z",
        "deletedAt": null,
        "registeredById": "35c5cc36-bb57-423f-9d52-3d1db2e71958",
        "registeredAtId": "f1c999b9-c1f8-4de2-bf43-fbf98a34a4b8",
        "territoryId": "84adf7d1-8293-4302-9d21-584dd116d3e1"
      }
  ]
}
```
</details>