# POS Dev Guides



# Clover Dev Guide

## Introduction

CloverPOS is a well documented API that allows us access by token, which must be provided by the merchant. The process for creating a token is simple and gives the user the ability to restrict our access to only the data we need.

## API Key Creation

Referencing the photos below:

<div class="cl-preview-section" id="bkmrk-click-setup-and-then">- Click setup and then click API Tokens link in left nav.
- Click the green **Create New Token** button.
- Name the token bartrack.
- Set the Read checkbox for the following: Inventory, Merchant, Orders. 
    - Click the green ***Create Token*** button.
- Click the eyeball icon next to the hidden private token. 
    - Copy and save the token for configuration!

</div><p class="callout warning">Two-factor authentication must be enabled by the merchant prior to creation of any token.</p>

[![image-1649259173576.png](https://wiki.bartrack.beer/uploads/images/gallery/2022-04/scaled-1680-/image-1649259173576.png)](https://wiki.bartrack.beer/uploads/images/gallery/2022-04/image-1649259173576.png)

[![image-1649259182043.png](https://wiki.bartrack.beer/uploads/images/gallery/2022-04/scaled-1680-/image-1649259182043.png)](https://wiki.bartrack.beer/uploads/images/gallery/2022-04/image-1649259182043.png)

## End-point usage

You’ll need your token and merchant ID. See: [https://docs.clover.com/reference](https://docs.clover.com/reference)

<div class="cl-preview-section" id="bkmrk-categories---get-all">- Categories - GET all item categories, includes the item ids in those categories.
    
    
    - `{{url}}/v3/merchants/{{mId}}/categories`
    - https://sandbox.dev.clover.com/v3/merchants/2CZXFDSA7MQ71/categories
- Orders - GET all a list of orders for merchant w/filter
    
    
    - `{{url}}/v3/merchants/{{mId}}/orders`
    - https://sandbox.dev.clover.com/v3/merchants/2CZXFDSA7MQ71/orders?filter=modifiedTime&gt;1497991264000&amp;filter=modifiedTime&lt;1497994264000
- Order Line Items - GET all line items from an order.
    
    
    - `{{url}}/v3/merchants/{{mId}}/orders/{{orderId}}/line_items`
    - https://sandbox.dev.clover.com/v3/merchants/2CZXFDSA7MQ71/orders//line\_items

</div>### Postman Collection

[https://www.getpostman.com/collections/0f3b1b40494d5b8501f4](https://www.getpostman.com/collections/0f3b1b40494d5b8501f4)

## Notes and Considerations

<div class="cl-preview-section" id="bkmrk-if-an-order-is-later">- If an order is later modified (next business day), that order would show up in the day modified.
- Uses Unix epoch timestamps.

</div>

# Future Dev Guide

## Introduction

The Windows BarTrack agent queries data from MSSQL server directly with a username and password. See [MSSQL username/password setup](https://stackedit.io/app#providerId=googleDriveWorkspace&folderId=1clzVw2PpsLZlxKgWFHAihMrmAw0vJ77e). **TODO:** link

## MSSQL Query Example:

<div class="cl-preview-section" id="bkmrk-"></div>```SQL
SELECT<br></br>	ItemName as item,<br></br>	DepartmentDescription as category,<br></br>	GroupName as subcategory,<br></br>	SoldDate as sale_timestamp,<br></br>	CAST((GrossPrice/100.00) as decimal(10,2)) as price,<br></br>	Quantity as quantity,<br></br>	ItemName+'|'+DepartmentDescription as sku,<br></br>	Cast((TotalTax/100.00) as decimal(10,2)) as tax,<br></br>	CONVERT(nvarchar(50), sitem.SaleID) as order_identifier,<br></br>	CONVERT(nvarchar(50), sitem.SaleItemID) as location_identifier,<br></br>	Cast(((GrossPrice-ActualPrice)/100) as decimal(10,2)) as adjustment,<br></br>	CASE WHEN VoidReason > 0 THEN REPLACE(VoidReason, VoidReason, 'true') ELSE REPLACE(VoidReason, VoidReason, 'false') END as voids<br></br>FROM<br></br>	dbo.SaleItem as sitem<br></br>	LEFT JOIN dbo.Sale as s ON s.SaleID = sitem.SaleID<br></br>	LEFT JOIN dbo.Department ON sitem.Department = Department.DepartmentName<br></br>	LEFT JOIN dbo.SaleItemDiscount as sid ON sitem.SaleItemID = sid.SaleItemID<br></br>WHERE s.CheckStatus <= 1<br></br>	AND s.IsTrainMode = 0<br></br>	AND sitem.IsModifier = 0<br></br>	AND sitem.SoldDate >= '2021-12-24T05:00:00' AND sitem.SoldDate <= '2021-12-25T04:59:00'<br></br>ORDER BY sitem.ItemName<br></br>
```

### Query Notes

<div class="cl-preview-section" id="bkmrk-item-sold-%40-timestam">- Item sold @ timestamp - SaleItem.SoldDate -or- SaleItem.AddDate
- Item name &amp; SKU - SaleItem.ItemName -or- SaleItem.ReceiptDescription | Department.DepartmentDescription | Department.GroupName
- Quantity - SaleItem.Quantity
- Category - Department.DepartmentDescription -or- Department.GroupName
- Raw Price of Item - SaleItem.Gross Price
- Order ID per item - SaleItem.SaleID
- Adjusted Price - SaleItem.Gross Price minus SaleItem.Actual Price
- Tax paid per item - Where Tax.TaxID GET Tax.TaxPercent multiplied by Gross Price
- Void - SaleItem.VoidDate is not NULL

</div>

# Heartland Dev Guide

## Configuration

```JavaScript
// Config.js<br></br>config.AUTHURL = 'https://hrpos.heartland.us';<br></br>config.GURL = 'https://api.hrpos.heartland.us/';<br></br>config.CATEGORIES_ENDPOINT = '/action/generateReport?format=CSV&report=CATEGORY_SALES';<br></br>config.ITEMS_ENDPOINT = '/action/generateReport?format=CSV&report=PURCHASE_ITEM_REPORT';<br></br>config.AUTH_ENDPOINT = '/index.php/api/user/login';
```

## Authentication

### Request Example

Obtain `mb_jwtoken` with POST request to `https://hrpos.heartland.us/index.php/api/user/login`

```JavaScript
{<br></br>	"email": location.username,<br></br>	"password": location.password<br></br>}
```

### Response Example  


```JSON
{<br></br>	"email": "technology@bartrack.beer",<br></br>	"mb_cache_token": "f19ad3860b06366fa8c40706b5e84b99",<br></br>	"rootState": "root.dashboard.snapshot",<br></br>	"mb_jwtoken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiI0MTQ0NCIsImVtYWlsIjoidGVjaG5vbG9neUBiYXJ0cmFjay5iZWVyIiwiZ3JvdXBJZCI6MiwibG9jYXRpb25JZCI6MTE1NDAsImFjY291bnRJZCI6OTk2MCwiZXhwIjoxNjM5NjE0ODE3fQ.qVWAsN4befntOecquGKq79MPn233Xm6FdfjZ_0zd8DM"<br></br>}
```

Pass the `mb_jwtoken` value as a Cookie to the header of GET request of `https://hrpos.heartland.us/index.php/api/accountuser/languageSettings`

```JSON
{<br></br>	headers: { Cookie: "mb_session = ${mb_jwtoken}" }<br></br>}
```

## SQL Info

<div class="cl-preview-section" id="bkmrk-sql-location_identif">- SQL `location_identifier` is actually employee ID

</div>

# Omnivore Dev Guide

You must have a developer account to access this information.  
You may register for an free account, but there should already be one in-house with access to actual locations.

Register Account  
[https://panel.omnivore.io/register](https://panel.omnivore.io/register)  
  
API Reference  
[https://panel.omnivore.io/docs/api/1.0](https://panel.omnivore.io/docs/api/1.0)

## Error Code Overview

The table below provides an overview of the most common and like error responses codes that Omnivore will throw, however, all valid HTTP response codes are possible. A full list of the HTTP error codes that Omnivore can throw can be found [here](https://panel.omnivore.io/docs/api/1.0/errors#http-status-codes).

<table id="bkmrk-status-cause-400---b" role="table"><thead><tr><th>Status</th><th>Cause</th></tr></thead><tbody><tr><td>400 - Bad Request</td><td>The request was malformed. Check to see if you sent all the required parameters and that all referenced resources exist.</td></tr><tr><td>401 - Unauthorized</td><td>The API key provided was invalid or you were unauthorized to handle the data.</td></tr><tr><td>402 - Payment Required</td><td>Your Account Plan doesn't have access to a resource or action on a resource. Upgrade your Plan to gain access.</td></tr><tr><td>403 - Forbidden</td><td>The resource requested is invalid.</td></tr><tr><td>404 - Not Found</td><td>The resource requested was not found on the server.</td></tr><tr><td>405 - Method Not Allowed</td><td>The request method is not supported for the requested resource.</td></tr><tr><td>500 - Interal Server Error</td><td>Something went wrong on our end. Please contact us if this persists.</td></tr><tr><td>503 - Service Unavailable</td><td>Your request could not be processed, most likely because a location is offline.</td></tr></tbody></table>

- - - - - -

#   


### 500 Error Response - POS Configuration Error

This error is described by Omnivore as, `The POS and/or integration points are not configured correctly` meaning that Omnivore needs to interact with the customer's back office computer to remedy the issue. Until the issue has been resolved there is no data available for us to pull.

**Error Message -**

```
[ Integration "omnivore" ] [ 90 ] Error: 500 - INTERNAL SERVER ERROR
{"errors":[{"description":"POS is not configured for the requested operation.","error":"pos_config_error"}]}
[ Integration "omnivore" ] [ 90 ] Establishment finished with error:
      Error: omnivore establishment "90" doesn't have "tickets" data for specified time period, unable to continue
    at Omnivore.<anonymous> (/home/ubuntu/bartrack-pos/integrations/cli/cli.js:1471:23)
    at Generator.next (<anonymous>)
    at fulfilled (/home/ubuntu/bartrack-pos/integrations/cli/cli.js:1419:58)
    at process._tickCallback (internal/process/next_tick.js:68:7)

```

**Email Sample -**

```
Recipient: Omnivore Support Email <support@omnivore.io>
Subject: 500 Error Response for Location ID #igXkjznT

---

Hello, I hope that this email finds you well. While attempting to pull data from this location we encountered the following error and need assistance remedying the issue so that we may perform our regular business operations. Here are the details of the impacted location, as well as the issue -

Customer Name: Primetime Sports Bar & Grille - Fairfax, VA
Location ID: igXkjznT
POS: POSitouch
Error Code: 500
Error: 'internal_server_error'
Error Description: 'POS is not configured for the request operation'

Please let us know if there is anything that we need to perform on our end to resolve the issue, we are looking forward to hearing from you soon, cheers!

```

#   


### 500 Error Response - Internal Server Error

This error is described by Omnivore as, `An unexpected error occurred` meaning that Omnivore dropped the ball and didn't properly handle whatever error was encountered on their end. Until the issue has been resolved there is no data available for us to pull.

**Error Message -**

```
[ Integration "omnivore" ] [ 81 ] Error: 500 - INTERNAL SERVER ERROR
{"errors":[{"description":"The system threw an unexpected error.","error":"internal_error"}]}
[ Integration "omnivore" ] [ 81 ] Establishment finished with error:
      Error: omnivore establishment "81" doesn't have "tickets" data for specified time period, unable to continue
    at Omnivore.<anonymous> (/home/ubuntu/bartrack-pos/integrations/cli/cli.js:1471:23)
    at Generator.next (<anonymous>)
    at fulfilled (/home/ubuntu/bartrack-pos/integrations/cli/cli.js:1419:58)
    at process._tickCallback (internal/process/next_tick.js:68:7)

```

**Email Sample -**

```
Recipient: Omnivore Support Email <support@omnivore.io>
Subject: 500 Error Response for Location ID #igXkjznT

---

Customer Name: Primetime Sports Bar & Grille - Fairfax, VA
Location ID: igXkjznT
POS: POSitouch
Error Code: 500
Error: 'internal_error'
Error Description: 'The system threw an unexpected error'

```

- - - - - -

#   


### 503 Error Response - Service Unavailable

This error is described by Omnivore as, `An attempt was made to interact with an offline location` meaning that the customer is likely experiencing Internet connectivity issues. Until that issue has been resolved we are unable to pull any data.

The Omnivore [documentation](https://panel.omnivore.io/docs/guides/providing_support/offline_locations#offline-notification) states that if the location has failed to respond for 5 minutes it will be deemed inaccessible. While the location is offline you'll receive HTTP 503 errors for all API calls to it. The most common causes are network disruption at the location or the back of house computer has been restarted.

When this occurs you can log into the Ommivore Control Panel and find the establishment in question from the list of Locations and then assess the current **Status** to determine if it is a brief or sustained issue. If the location is offline then the only solution to this problem is to investigate the status and try again later when they come back online

**Error Message -**

```
[ Integration "omnivore" ] [ 82 ] Error: 503 - SERVICE UNAVAILABLE
{"errors":[{"description":"Location ingXgy5T not available - agent offline","error":"agent_offline"}]}
[ Integration "omnivore" ] [ 82 ] Establishment finished with error:
      Error: omnivore establishment "82" doesn't have "tickets" data for specified time period, unable to continue
    at Omnivore.<anonymous> (/home/ubuntu/bartrack-pos/integrations/cli/cli.js:1471:23)
    at Generator.next (<anonymous>)
    at fulfilled (/home/ubuntu/bartrack-pos/integrations/cli/cli.js:1419:58)
    at process._tickCallback (internal/process/next_tick.js:68:7)

```

# Restaurant Manager Dev Guide

This is a three step process that calls ahead to an end-point with a POST along with site specific cert. It returns a list of signed, time-sensitive urls S3 for each file to upload by the BT Client. Once completed it calls GET on the batch for final processing after the uploads have been confirmed. Note that the file name of the export must match this name, it’s expectations based on the point-of-sale type.

# SmartTab Dev Guide

##### **Integration Type: - Undocumented API**

## Parameters Used

<div class="cl-preview-section" id="bkmrk-venueid%3D1%26_%3D16384686">- venueId=1&amp;\_=1638468699524
    
    
    - **TODO:** - Need to discover what the second param \_ is for.
- timeZone
- timeStart
- timeEnd
- date

</div>## Local Storage Keys

```
token: U2FsdGVkX183RZIJk5oO/AuYZbG6KES7q+E/2DoSSAAcX9l+6pduyb6uhJuTV46l
```

## Request Headers

```
Request-Method: GET<br></br><br></br>Authorization: Basic bWZsb3JlczpGbG9yZXMxNjA=
```

## Tabs Endpoint

I’m not sure yet if the mflores is a private sandbox api, or if that URL will be establishment specific.

##### Example URL:

`https://api-mflores.smarttab.com/api/report/tabReport/?timeStart=05%3A00%3A00&timeEnd=05%3A00%3A00&timeZone=America%2FNew_York&date=2020-10-05&venueId=1&_=1638468699524`

### Response JSON Example:

```JSON
[<br></br>  {<br></br>    "id": "30cc598f-58f9-4a3f-a4b0-381360d521a0",<br></br>    "paymentId": null,<br></br>    "ticketId": "3846f386-36e5-4281-8948-fe47566824d9",<br></br>    "tableId": null,<br></br>    "customerId": null,<br></br>    "dayOrdinalNumber": 1,<br></br>    "subNumber": null,<br></br>    "tabStatus": "OPENED", //FILTER CLOSED ONLY<br></br>    "paymentStatus": null,<br></br>    "amount": null,<br></br>    "tips": null,<br></br>    "balanceDue": 39.18,<br></br>    "total": 39.18,<br></br>    "lastFourSymbols": null,<br></br>    "smartTabFee": null,<br></br>    "tableName": null,<br></br>    "closeTime": null,<br></br>    "dayTimestamp": "2020-10-05 00:00:00",<br></br>    "tabName": "Test",<br></br>    "paymentTender": null,<br></br>    "customTender": null,<br></br>    "creditTender": null,<br></br>    "refundAmount": null,<br></br>    "cardDataInputMethod": null,<br></br>    "paymentSource": null,<br></br>    "kioskMode": false,<br></br>    "ownerId": 173,<br></br>    "tabType": "BAR_TYPE",<br></br>    "ownerName": "Michael Flores",<br></br>    "customerName": "Test",<br></br>    "tender": null,<br></br>    "status": "OPENED",<br></br>    "hasVoids": false,<br></br>    "hasDiscounts": false,<br></br>    "hasComps": false,<br></br>    "voidsNum": null<br></br>  }<br></br>]<br></br><br></br>
```

## Ticket Endpoint

I’m not sure yet if the mflores is a private sandbox api, or if that URL will be establishment specific.

##### Example URL:

`https://api-mflores.smarttab.com/api/tab/ticketView?id=30cc598f-58f9-4a3f-a4b0-381360d521a0&venueId=1&_=1638468699525`

### Response JSON Example

*only showing pieces of data we’re looking for, this response has a huge tree for a single row*

```JSON
{<br></br>    "productId": 894,<br></br>    "itemizedDiscountAmount": 0<br></br>    "isVoided": false,<br></br>    "creationTime": "2020-10-05 21:27:15.459+00"<br></br>    "deleted": false,<br></br>    "created": "2020-10-05 21:27:26+00"<br></br>    "modifiers": [],<br></br>    "name": "EAGLE SHOT",<br></br>    "price": 10,<br></br>    "classId": 2,<br></br>    "multiplier": 1,<br></br>    "adjustedGrossPrice": 9.09,<br></br>    "netPrice": 9.09, 72<br></br>    "quantity": 1,<br></br>    "subClassId": null,<br></br>    "priceWithModsAndMultiplier": 10,<br></br>    "includedTax": 1.07,<br></br>    "excludedTax": 0<br></br>}<br></br>
```

## Categories/Products Sold Endpoint

`https://api-mflores.smarttab.com/api/report/product/?dateStart=2021-01-01&dateEnd=2021-10-31&timeStart=05%3A00%3A00&timeEnd=05%3A00%3A00&timeZone=America%2FNew_York&classId%5B%5D=1&classId%5B%5D=2&classId%5B%5D=3&showSold=1&showNotSelling=0&venueId=1&_=1638566076252`

### Response JSON Example:

```JSON
[<br></br>    {<br></br>	    "type": "BEER",<br></br>	    "classId": 1,<br></br>	    "cost": "3.30",<br></br>	    "quantity": "1",<br></br>	    "productId": 761,<br></br>	    "name": "SUDWERK PILSNER ",<br></br>	    "roleIds": [1],<br></br>	    "employeeIds": [173]<br></br>    },<br></br><br></br>    {<br></br>	    "type": "BEER",   <br></br>	    "classId": 1,<br></br>	    "cost": "4.13",<br></br>	    "quantity": "1",<br></br>	    "productId": 209,<br></br>	    "name": "BUD LIGHT",<br></br>	    "roleIds": [1],<br></br>	    "employeeIds": [173]<br></br>	}<br></br>]<br></br>
```

## References:

[SmartTab Integration Notes (JIRA)](https://bartrack.atlassian.net/browse/BAR-950)

# Square Dev Guide

##### **Integration Type: - [Documented API](https://developer.squareup.com/reference/square)**

## Parameters Used

### Caveats

<div class="cl-preview-section" id="bkmrk-voids-are-not-availa"><div class="cl-preview-section">- Voids are not available on this integration. 
    - Due to the way voids are handled in the API data (not the visual report data), they no longer exist as an item line in the data set. Instead you have to listen to their webhook for monitoring order modifications as the Square API does not support it.

</div></div>### Get Location

**GET**: `https://connect.squareup.com/v2/locations`  
`location` is needed as a parameter in the request for orders.

#### Headers

<div class="cl-preview-section" id="bkmrk-authorization%3A-beare"><div class="cl-preview-section">- `Authorization: Bearer {token}`

</div></div>### Get Catalogs

**GET**: `https://connect.squareup.com/v2/catalog/list?types=category,item,item_variation`  
Catalogs are needed to determine an item’s category.

#### Headers

<div class="cl-preview-section" id="bkmrk-authorization%3A-beare-0">- Authorization: Bearer {token}

</div>#### Parameters

<div class="cl-preview-section" id="bkmrk-cursor-initial-reque"><div class="cl-preview-section">- `cursor`
    - Initial request is without `cursor`. If response includes `cursor` then paginate using response `cursor`.
    - If no `cursor` is returned then it is the last page.

</div></div>### Get Orders

**POST**: `https://connect.squareup.com/v2/orders/search`

#### Headers

<div class="cl-preview-section" id="bkmrk-authorization%3A-beare-1">- Authorization: Bearer {token}

</div>#### Body Parameters

<div class="cl-preview-section" id="bkmrk-location_id-as-per-r">- `location_id` as per response from get location
- `sales_start` format `YYYY-MM-DDTHH:MM:ssZ`
- `sales_end` format `YYYY-MM-DDTHH:MM:ssZ`

</div>#### Body Example

```
{  
	"location_ids": [  
		{location_id}  
	],  
	"query": {  
		"filter": {  
			"date_time_filter": {  
				"closed_at": {  
					"start_at": {sales_start},  
					"end_at": {sales_end}  
				}  
			},  
			"state_filter": {  
				"states": [  
					"COMPLETED"  
				]  
			} 
		},  
		"sort": {  
			"sort_field": "CLOSED_AT",  
			"sort_order": "DESC"  
		}  
	}
}

```

#### Response JSON Example:

```
[
	{  
		"id": "kTmqQ6TTaKVY8KlcbAJEQSyeV",  
		"location_id": "GXFWQJMA4XGBA",  
		"line_items": [  
			{  
				"catalog_object_id": "NPOXBH3AEIFOQUMJGDLELNZC",  
				"quantity": "1",  
				"name": "8- Gingers Revenge fig and vanilla",  
				"variation_name": "Regular",    
				"modifiers": [  
					{  
						"name": "12oz"
					}  
				],  
				"gross_sales_money": {  
					"amount": 600
				},  
				"total_tax_money": {  
					"amount": 45,  
				},  
				"total_discount_money": {  
					"amount": 60,  
				}
			}
		]
	}
]


```

### References:

[Square Integration Notes (JIRA)](https://bartrack.atlassian.net/browse/BAR-1174)

# Touch Bistro Dev Guide

##### **Integration Type: - Undeveloped**

## References:

[Touch Bistro Integration Notes (JIRA)](https://bartrack.atlassian.net/browse/BAR-687)

# GoTab Dev Guide

GoTab API explorer:  
[https://gotab.io/api/graph](https://gotab.io/api/graph)<span style="color: #d1d2d3; font-family: Slack-Lato, Slack-Fractions, appleLogo, sans-serif; font-size: 15px; font-style: normal; font-variant-ligatures: common-ligatures; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #222529; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">   
[https://studio.apollographql.com/sandbox/schema/reference/objects/Item?query=returnType%3ADatetime](https://studio.apollographql.com/sandbox/schema/reference/objects/Item?query=returnType%3ADatetime)  
[https://docs.gotab.io/reference/objects#item](https://docs.gotab.io/reference/objects#item)</span>

List of order statuses:

- PENDING
- SCHEDULED
- SENT
- IN\_TRANSIT
- DELIVERED
- OFFLINE\_DELIVERED
- RECALLED
- VOIDED
- RESET

 All items ordered on a tab for that fiscal day:

```
curl -L -X POST 'https://gotab.io/api//graph' \<br></br>-H 'Authorization: BearerToken' \<br></br>-H 'Content-Type: application/json' \<br></br>--data-raw '{"query":"query($locationUuid: String!) {\n  location(locationUuid: $locationUuid) {\n    tabsList(\n      filter: {\n        fiscalDay: { equalTo: \"2022-08-26\" }\n        status: { equalTo: \"CLOSED\" }\n        ordersPlaced: {greaterThan: 0}\n      }\n    ) {\n      tabUuid\n      href\n      name\n      status\n      numGuests\n      tabMode \n      tax\n      subtotal\n      autograt\n      total\n      opened\n      closed\n      orderType\n      server {\n        userId\n        name\n      }s\n      itemsList(\n        filter: {\n          ordered: {equalTo: true}\n        }\n      ) {\n        fee\n        discount\n        comped\n        voided\n        status\n        name\n        itemId\n        taxRate\n        taxRateDetail\n        sku\n        subtotal\n        subtotalInitial\n        options {\n          name\n          shortName\n          isProduct\n          price\n          quantity\n        }\n        adjustments {\n          itemAdjustmentId\n          quantity\n          unitPrice\n          adjustmentReason\n          adjustmentType\n        }\n        accountingStream {\n            accountingStreamUuid\n            name\n            reportingGroup\n        }\n    }\n    }\n  }\n}","variables":{"locationUuid":"NA2RpxKdptZYnHOA3Z~eIo4E"}}'
```

# SpotOn

Please see "Requesting API Access" here:

[SpotOn Establishment Setup Documentation](https://developers.spoton.com/enterprise/docs/enabling-api-access "https://developers.spoton.com/enterprise/docs/enabling-api-access")

# SpotOn

See official documentation:

[https://wiki.bartrack.beer/books/pos-integrations/page/spoton](https://wiki.bartrack.beer/books/pos-integrations/page/spoton "See Official Documentation")

# New Establishment or Integration

1. New integrations and establishment config will be added to staging first.
2. Integration would be tested in three parts:
    
    
    1. individual establishment.
    2. all establishments of integration type.
    3. finally, all integrations/establishments (full daily automation)
3. These types of failure must be tested:
    
    
    1. establishment has no data.
    2. connection failure.
    3. any type of breakage in one integration, does not cause break in another.

