HotSchedules IoT Platform
The HotSchedules Bodhi Platform is a set of REST APIs that power the Clarifi suite of applications - gathering data from a variety of sources and allowing a restaurant manager to gain both just-in-time as well as forward-looking insights into how they can improve their business.
This document is meant to be a resource for software developers who want to interact with our data set. We will be taking a particular eye towards interacting with existing point-of-sale and existing labor schedule data, as well as how to pass in point-of-sale data in our canonical data model, so that applications can consume it.
Building Blocks
The Bodhi Platform is built as a series of namespaces. A namespace represents the data store for 1 company, and has a collection of stores under it. A store represents a single venue, and some of the elements of a store are what you would expect from a venue: address, business hours, etc.
Users can be created within a namespace and assigned to a set of stores within a hierarchy, and assigned profiles that are sets of permissions to control what they can or cannot do within various applications.
An admin profile represents the top level of permissions within a namespace, and is needed in order to GET and POST data to our REST APIs.
For our purposes within this document, we are going to refer to users as people or machines who have access to a username and password that has the admin profile within their namespace, and can thus authenticate to the API.
To move forward, make sure you have acquired the following:
- A namespace
- A username and password with the admin profile
We will be using Postman as our tool to test and validate many of the elements discussed within this doc, so we highly recommend taking a moment to download it and familiarize yourself with its functionality. Our Platform also includes a Query tool and additional interactive docs that you can use to interact with our dataset (keep reading!).
URLs
The Bodhi Platform is built around a central URL: https://api.hotschedules.io. We also have components and applications available at other tiers such as,
The syntax of your URL will include your namespace name within it. For example, a call to return data about all of the Stores in your namespace would look like this:
https://api.hotschedules.io/namespace/resources/Store
You’ll be seeing this a lot. Our API uses Mongo DB for storage, so to learn more about this foundation, see this link: http://docs.mongodb.org/manual/reference/operator
You may be unfamiliar with the REST query syntax. If you’re familiar with SQL, you should note the same types of SQL query operations are possible using the REST API.
To learn more about the semantic differences, see this document: http://docs.mongodb.org/manual/reference/sql-comparison. No need to do it right now - you can come back to it later!
Tokens
Authenticating to the REST API requires generating a JWT, or Java Web Token. For more information around JWTs, see this link: https://jwt.io/introduction/
Internally, we refer to capturing and refreshing JWTs as “IDM” or “Identity Management” – so if you see or hear reference to IDM, they are talking about authenticating a user via a JWT (as opposed to a simple username/password combo).
For more details on IDM, please click HERE.
Before you can retrieve your token, follow these simple setup steps before proceeding.
Step 1: Create your global profile.
Step 2: Obtain your API credentials from HotSchedules if you have not already done so.
Step 3: Login into the Account Manager
Step 4: In the upper right corner, select the wrench icon, then keychain, then your namespace.
Step 5: Enter your API credentials as provided by hotSchedules and click save.
Step 6: Continue with the example below to retrieve your token.
Your application will need to not only pass a JWT as part of requests it makes to the REST API, but also refresh that token programmatically when it expires.
To generate a JWT, you’ll need to POST your request to the following URL: https://login.hotschedules.io/auth/realms/hotschedules/protocol/openid-connect/token
With the following information:
Header
- content-type: application/x-www-form-urlencoded
Params
grant_type
- Value must be “password”
client_id
- Value must be “urn:mace:oidc:hotschedules.com”
username (this is your global profile username)
- Value should reflect the username of account you’re requesting tokens for
password (this is your global profile password)
- Value should reflect the password of the account you’re requesting tokens for
You should return 3 items:
- Access token
- Refresh_token
- Id_token
The Id_token is your JWT – save that!
Here’s an example response (with the JWT bolded)
The tokens generally are active for 8 hours, and thus would need to be refreshed on that schedule. Refreshing the token is very similar, just hit this URL:
https://login.hotschedules.io/auth/realms/hotschedules/protocol/openid-connect/token
Header
- content-type: application/x-www-form-urlencoded
Params
grant_type
- Value must be “refresh_token”
client_id
- Value must be “urn:mace:oidc:hotschedules.com”
refresh_token
- Value should reflect the token you are attempting to refresh
As a human interacting with this data, generating a new token each time is handy to do, but your application should eventually automate the process of refreshing its token.
Now that you know how to authenticate to the REST API, let’s create a Store!
Creating A Store
We have a namespace, but we have no stores to post any data to! Let’s fix that right now.
As mentioned before, the Store endpoint is: https://api.hotschedules.io/namespace/resources/Store
The Store endpoint allows you to post and receive a great deal of information about the configuration of your store - addresses, contact information, business hours, an identifying image, etc.
The minimum amount of data to pass in to create a Store in your namespace, and the expected types, are:
{ “name”: “String”, “display_name”: “String”, “store_number”: “String”, “organization_id”: “String”, “concept”: “String”, “status”: “String”, “website_url”: “String”, “telephone”: “String”, “timezone”: “String”, “organization_name”: “String” }
If you replace the “Strings” in the above example with actual data corresponding with your restaurant, POST that to the URL above with your JWT as the bearer token, you should receive a Status: 201 response with the text: “Created”.
Success! Nicely done, you’ve created your first store.
If you get an error message, the Store endpoint will give you some additional information about an object that may be misattributed, or an error in the syntax.
What are all these IDs?
You’ll be interacting with several different types of IDs throughout this process, and it’s important to keep these straight. Many of these IDs are meant as an “external reference” value, to match an ID that may be in place within a different application, either within the Clarifi ecosystem or external, as opposed to a “sys_id” which is meant to identify a particular object within the Mongodb database the REST API is calling.
A “concept ID” is a value meant to indicate a grouping of stores, so each store will need its own “store_number” and multiple stores can roll up to a single “concept” ID.
Introducing the Bodhi Query Tool
Before we move away from interacting with Stores and start interacting with individual components, it’s time to familiarize yourself with the Query tool - a handy way to interact with the API within our product itself!
The Query tool can be found at this URL: https://tools.hotschedules.io/query
The Query tool will save you a lot of time, in that it has a UI that will allow you to input the parameters you are attempting to search, auto-fill in with available options, and provide you with the output as well as the final URL you can use to access your data.
In the top nav bar, enter Store and click Send. As long as the drop down on the left is set to GET, you will be performing a GET on the Store type and the API should return all the data about Stores in your namespace.
If, in the previous step, you went hog wild and created several stores, you may want to search just for one particular store, maybe the first one you created. So let’s look at how the UI allows you to narrow your search. In this case let’s grab the sys_id of one particular store, and then do a GET to get just the data related to that Store object.
In the Fields box, click to open the drop down of available fields, and choose display_name and sys_id. Click Send!
In my namespace, this returns just the display_name and sys_id of all my stores:
If I want to just see the data for my store “Airwaves Cafe”, I can then plug the sys_id in the “where” clause of the tool:
As you gain more experience with the Bodhi REST API, it is likely that the Query tool will become a very good friend of yours.
Now that we’re able to authenticate to the API, create and get objects, and use the Query tool, let’s talk about POS data.
Clarifi API Service
Introduction
We have built multiple POS integrations that source raw data in a variety of ways - SQL queries, DBF files, APIs - and transform that data into a generalized format that we refer to as “canonical”. Since different POS’s have different object names, types, and other architectures, transforming that data into a canonical format helps provide a standard dataset that the different Clarifi applications to call to and consume in order to provide value to their users.
Thus, if you are tasked with building a POS integration of your own to enable your customers to use Clarifi, then you will need to pass in some canonical data. So let’s take a look at what it is!
StoreInfo and StoreBusinessDay
There are two main components to the Clarifi POS canonical data model. We collect definitions of elements at a store - the employees, their job codes and pay rates, menu items and their pricing, sales categories, revenue centers, and more! These elements collectively we refer to as StoreInfo. Secondly, we collect events that occur at the store - the transactions that were generated, the items that were sold, sales totals, timecards that are generated, and more. These items were collectively refer to as StoreBusinessDay.
StoreInfo = definition of elements
StoreBusinessDay = events involving those elements
For example, a StoreBusinessDay timecard may indicate that Employee #12 clocked in as Job 26 at 3:00pm - a Clarifi application would take this data from StoreBusinessDay and be able to lookup to StoreInfo that Employee #12 is named David and Job 26 is Bartender, and give information to an end user about Jason clocking in as a Bartender.
Let’s take a look at the Types of data that make up StoreInfo and StoreBusinessDay, and then we’ll take a look at how exactly to pass that information into our REST API.
StoreInfo types
PosEmployee: PosEmployee’s represent a list of data about the employee profiles that are housed in the POS.
Here’s a breakdown:
- Name - The first and last name of the employee
- Nickname - The employee’s nickname or assumed moniker.
- Birthdate - the employee’s date of birth
- Addresses - The street, city, state, zipcode, and country assigned to the employee
- Emails - the employee’s email address
- Status - whether or not the employee is terminated
- Employment Period - the span of time between the employee’s hire date and last day.
- Instore_id - A ID meant to identify the employee at the store level
- HR ID - An ID meant to identify the employee at a company level (i.e. across multiple stores)
- Phone Numbers - the employee’s phone numbers
Additional StoreInfo types:
PosJob: A comprehensive list of jobs or roles available for employees to clock in as.
pmPosEmployeePosition: An employee position indicates which PosEmployees are assigned which PosJobs, along with their designated payrate.
PosRevenueCenter: A list of revenue centers within a venue, such as “Bar” “Patio” “Dining Room”, etc.
PosSalesCategory: A list of types of items being sold at this venue, such as “Food”, “Liquor” ,“Beer”, “NA Bev”, “Retail”, etc.
PosMenu: A list of menus available within the POS, such as “Dinner”, “Happy Hour”, etc
PosMenuItems: A list of menu items and pricing available for sale at the venue.
PosMenuModifiers: A list of menu items that would be classified as modifiers, i.e. attachments to menu items.
StoreBusinessDay Types
PosPunch: The punch records that are present in the point of sale system.
PosCheck: The different transactions at a restaurant.
PosCheckItem: The items that make up a transaction. Items listed here roll into PosCheck.
A full breakdown of each type can be found in the Getting Data From Clarifi section below.
Do I have to send you all this stuff?
Not at all! As we get deeper into building and validating the data itself, you’ll find that some fields are required and some are not. If a field is required but is irrelevant to your business, you can leave it with a null value.
For instance, you may only have a single menu at your venue. In that case, you would populate a single PosMenu, and your PosMenuItems would roll up to that PosMenu. Similarly, if you haven’t collected your employee email addresses, your PosEmployee’s do not need to have that field filled out.
We have some validation tools we’ll discuss later on to hone in on what is and is not required.
Getting Data From Clarifi
HotSchedules provides a tool called “Bodhi Query” which can be used to interact with the Clarifi API. Using the query tool will allow you to get store data such as the “sys_id”. The query tool also alllows the user to to use RESTful verbs to get, set and update data within Clarifi.
To familiarize yourself with the query tool, start by logging into to your namespace.
Login to your namespace: https://tools.hotschedules.io
Once you have authenticated to your namespace, you will be on the tools page where you will select “Bodhi Query”
The Bodhi Query tool will allow you to use the GET verb to access dta relevant to your store. Let’s use the Query tool to get the sys_id of a store.
In the primary window, there are 2 select boxes. Box 1 is where you will select the verb type and box 2 provides the service from which to access.
In this example, we are using the GET verb and the API service to get the store data. In the “Type Name” field, enter “Store” and click the send button. A list of store for your namespace will be returned.Within the body of the JSON response, locate the sys_id.
Now that we have the sys_id of a store, we will use “Package” to query the StoreInfo of a specific store. Selec the GET verb as the method and the Package as the service type. In the “Type Name” field enter “StoreIno”. To narrow to a specific store, we will use the Where clause. Enter “store_id” in the first field and the “sys_id” in the 2nd field and then select the send button. The results of your call will be displayed in the main body of the query tool.
The Query Tool can be used to get or set data to any of the POSTypes listed below. As noted in this documentation, you can try different calls using the Where and Fields paramaters to narrow data to more specific details.
Using our RESTful service, a call can be made to GET data from the API. Examples of the various calls are listed below with sample JSON Outputs. The file spec is available for download providing the data points and the expected data type for each field.
HTTP Status Codes provide a description of the sucess or failure of a call: https://httpstatuses.com
Base Call: https://api.hotschedules.io/namespace/resources/PosCheck?paging=limit:25,page:1
Using a field in the where or fields clause will narrow the focus to specific data.
Below you will find descriptions for each canonical type that we use and the available fields.
PosEmployee, PosJob, PosEmployeePosition, PosRevenueCenter, PosMenu, PosMenuItems and PosMenumodifiers are only types that are queryable via StoreInfo.
Example: To get a list of employees for a specific store and associated values, this would be the query string used
Note: store_id is the sys_id of the store you are running the call for. To retrieve the list of sys_id’s for all stores, use the following call.
https://api.hotschedules.io/namespace/resources/Store?fields=name,sys_id&paging=limit:25,page:1
EXAMPLE JSON RESPONSE:
[
{
name: "store_test_07",
sys_id: "5a1653d772bd660b0e9270bc"
},
{
name: "store_test_05",
sys_id: "5a1653d79534035f755308cf"
}
]
PosEmployee
A list of employees pulled from the point of sale.
- Name - The first and last name of the employee.
- Nickname - The employee’s nickname or assumed moniker.
- Birthdate - The employee’s date of birth.
- Addresses - The street, city, state, zipcode, and country assigned to an employee.
- Emails - The employee’s email address.
- Status - Whether or not the employee is terminated.
- Employment_period - The span of time between the employee’s hire date and last day.
- Instore_id - The point of sale id given to the employee.
- Hr_id - The ID given to the employee by the company.
- Phone_numbers - The employee’s phone number.
EXAMPLE JSON RESPONSE:
[
{
"store_employees": [
{
"name": {
"family_name": "DO NOT REMOVE",
"given_name": "ATO TRAINING 5"
},
"nickname": "ATO TRAINING 5",
"birthdate": null,
"addresses": [
{
"street_address": null,
"extended_address": null,
"locality": null,
"region": null,
"postal_code": null,
"country": null
}
],
"status": "Active",
"employment_period": {
"from": "2018-04-03T00:00:00.000Z"
},
"instore_id": "905",
"hr_id": "",
"phone_numbers": [],
"store_id": "5a1653d772bd660b0e9270bc",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180403/StoreInfo",
"store_reference": {
"id": "7"
}
}
]
Posjob
A list of job codes from the customer’s point of sale system.
- Instore_name - The name of the job code.
- Instore_id - The point of sale ID given to the job code.
- regular _rate - The pay rate attached to the job code.
- Overtime_rate - The overtime rate attached to the job.
- Doubletime_rate - The doubletime rate assigned to the job.
Example: To get a list of jobs for a specific store and associated values, this would be the query string used
EXAMPLE JSON RESPONSE:
[
{
"store_jobs": [
{
"instore_name": "Server",
"instore_id": "1",
"regular_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"overtime_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"store_id": "5a1653d772bd660b0e9270bc",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180403/StoreInfo",
"store_reference": {
"id": "7"
}
}
]
PosEmployeePosition
The job code assigned to the employee in the point of sale.
- Employee_reference - The employee’s POS ID.
- Job_reference - The job code’s POS ID.
- Regular_rate - The job code rate given to the employee.
- Overtime_rate - The overtime rate given to the employee.
- Doubletime_rate - The doubletime rate give to the employee.
- PosSalesCategory - The sales categories listed in the point of sale.
- Instore_id - The point of sale ID given to the sales category.
- Name - The name of the assigned sales category.
Example: To get a list of positions for a specific store and associated values, this would be the query string used
EXAMPLE JSON RESPONSE:
[
{
"employee_positions": [
{
"employee_reference": {
"id": "905",
"name": "ATO TRAINING 5 DO NOT REMOVE"
},
"job_reference": {
"id": "12"
},
"regular_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"overtime_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"doubletime_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"store_id": "5a1653d772bd660b0e9270bc",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180403/StoreInfo",
"store_reference": {
"id": "7"
}
}
]
PosRevenueCenter
The revenue centers listed in the point of sale.
Download File Spec
- Instore_id - The point of sale ID given to the revenue center.
- Name - The name of the revenue center.
Example: To get a list of revenue centers for a specific store and associated values, this would be the query string used
EXAMPLE JSON RESPONSE:
[
{
"revenue_centers": [
{
"name": "Dining",
"instore_id": "1",
"store_id": "5a1653d772bd660b0e9270bc",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180403/StoreInfo",
"store_reference": {
"id": "7"
}
},
{
"name": "Bar Downstairs",
"instore_id": "2",
"store_id": "5a1653d772bd660b0e9270bc",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180403/StoreInfo",
"store_reference": {
"id": "7"
}
}
]
PosMenu
Different menu types. Examples can include things like a brunch or dinner menu.
Note: PosMenu is nested within StoreInfo
- Name - The name of the menu
- Category - The category assigned to a menu.
- Items - The items that make up a menu.
- Modifiers - The modifiers that can be used by items in the menu.
PosMenuItems
The items that can be used in all of the different menus.
Note: PosMenuItems are nested within StoreInfo
- Id - The point of sale ID given to a menu item.
- Name - The name of the item in the point of sale.
- Category - The category that an item is assigned to.
- Description - an extension of the name that can provide further information about the item.
- Unit_price - The default menu price of the item.
- Prices - If that item has a different price associated with it outside of the default. For example a cocktail might have a happy hour price outside of the menu price.
PosMenumodifiers
Things like ketchup that can be used in tandem with a menu item.
Note: PosMenumodifiers are nested within StoreInfo
- Id - The given point of sale ID for the menu modifier.
- Name - The name of the menu modifier.
- Description - A longer version of the name that can provide further insight into the name.
- Unit_price - The default menu price for a particular modifier.
- Prices - Any other prices outside of the menu price that is associated with the modifier.
Example Call to retrieve PosMenu, PosMenuItems and PosMenumodifiers: https://api.hotschedules.io/namespace/resources/StoreInfo?where={“store_id”: { “$eq”: “5a1653d772bd660b0e9270bc” }}&fields=store_menus&paging=limit:25,page:1
EXAMPLE JSON RESPONSE:
{
"store_menus": [
{
"store_id": "5a1653d772bd660b0e9270bc",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180403/StoreInfo",
"store_reference": {
"id": "7"
},
"name": "Test Printers",
"items": [
{
"id": "400520",
"name": "Expo Test",
"description": "Expo Test",
"unit_price": {
"value": 0,
"scale": 2,
"code": "USD"
}
},
{
"id": "400521",
"name": "Fry Test",
"description": "Fry Test",
"unit_price": {
"value": 0,
"scale": 2,
"code": "USD"
}
},
{
"id": "400522",
"name": "Grill Test",
"description": "Grill Test",
"unit_price": {
"value": 0,
"scale": 2,
"code": "USD"
}
},
{
"id": "400523",
"name": "Saute Test",
"description": "Saute Test",
"unit_price": {
"value": 0,
"scale": 2,
"code": "USD"
}
},
{
"id": "400524",
"name": "SVR UP",
"description": "SVR UP",
"unit_price": {
"value": 0,
"scale": 2,
"code": "USD"
}
},
{
"id": "400525",
"name": "SVR BAR",
"description": "SVR BAR",
"unit_price": {
"value": 0,
"scale": 2,
"code": "USD"
}
}
],
"modifiers": []
}
PosPunch
The punch records that are present in the point of sale system.
- Employee_reference - the employee’s given point of sale ID.
- Job_reference - The given point of sale ID for the job code that is assigned to the employee.
- Business_day - The business day that the employee has worked.
- Started_at - The time that the employee started working at.
- Ended_at - The time that the employee stopped working at.
- Total_minutes_worked - The total amount of time that the employee worked.
- Breaks - The number of breaks that the employee took.
- Regular_rate - The regular rate that the employee is working at
- Overtime_rate - The overtime rate that the employee is working at
- Doubletime_rate - The doubletime rate that the employee is working at.
- Declared_tips - The declared tips that the employee has.
- Cash_tips - The cash tips that the employee has.
- Credit_tips - The credit tips that the employee has.
Example: get punch records https://api.hotschedules.io/namespace/resources/PosPunch?where={“store_id”: { “$eq”: “5a1653d772bd660b0e9270bc” }}&fields=employee_reference&paging=limit:25,page:1
EXAMPLE JSON RESPONSE:
{
"employee_reference": {
"id": "395"
},
"job_reference": {
"id": "10"
},
"business_day": "2008-01-10",
"started_at": "2008-01-10T12:32:00.000Z",
"ended_at": "2008-01-11T04:00:00.000Z",
"total_minutes_worked": 928,
"overtime_minutes_worked": 0,
"breaks": [],
"regular_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"overtime_rate": {
"value": 0,
"scale": 2,
"code": "USD"
},
"tips": {
"declared_tips": {
"value": 0,
"scale": 2,
"code": "USD"
}
},
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180331/StoreBusinessDay",
"store_reference": {
"id": "7"
},
"store_id": "5a1653d772bd660b0e9270bc",
"key": "79e5a5c698d0c09fd66fb927d97b3dae",
"sys_version": 4,
"sys_created_at": "2018-03-28T13:13:20.165Z",
"sys_created_by": "admin",
"sys_type_version": 6,
"sys_modified_at": "2018-03-31T17:00:24.001Z",
"sys_modified_by": "admin",
"sys_id": "5abb94f03d0408724e91e8db"
}
PosCheck
The different transactions at a restaurant.
- Check_id - The point of sale ID given to the transaction.
- Voided - Whether or not the transaction was voided.
- Canceled - Whether or not the check was cancelled.
- Employee_reference - The point of sale ID given to the employee who handled the transaction.
- Table_id - The point of sale ID given to the table.
- Register_id - The point of sale ID given to the register.
- Shift_id - The given point of sale ID for the shift.
- Opened_at - When the transaction was opened.
- Closed_at - When the transaction was closed.
- Guest_count - The total number of guests that were present for the transaction.
- Item_count - The total number of items on the transaction.
- Net_total - The total without taxes or coupons applied to it.
- Gross_total - The total including taxes and coupons.
- Discount_total - The total after any discounts have been applied to it.
- Tax_total - The total with the tax applied to it.
- Tender_total - The total amount of dollars paid.
- Change_total - The total amount of change paid.
- Gratuity_total - Any gratuity that was given to the transaction.
- Void_total - if the check was voided how much was it for.
- Items - The items that are on the transaction.
EXAMPLE JSON RESPONSE:
{
"business_day": "2018-03-26",
"check_id": "60025",
"employee_reference": {
"id": "922"
},
"net_total": {
"value": 500,
"scale": 2,
"code": "USD"
},
"gross_total": {
"value": 58198,
"scale": 2,
"code": "USD"
},
"discount_total": {
"value": 0,
"scale": 2,
"code": "USD"
},
"tender_total": {
"value": 70198,
"scale": 2,
"code": "USD"
},
"shift_id": "1",
"revenue_center": {
"id": "1"
},
"opened_at": "2018-03-26T18:00:00.000Z",
"closed_at": "2018-03-26T19:19:00.000Z",
"canceled": false,
"item_count": "4",
"content_url": "namespace/5a1653d772bd660b0e9270bc/20180326/StoreBusinessDay",
"store_reference": {
"id": "7"
},
"store_id": "5a1653d772bd660b0e9270bc",
"items": [
{
"item_code": "55032",
"quantity": "1",
"sales_category": {
"id": "4"
},
"gross_total": {
"value": 500,
"scale": 2,
"code": "USD"
},
"net_total": {
"value": 500,
"scale": 2,
"code": "USD"
},
"tax_total": {
"value": 0,
"scale": 2,
"code": "USD"
},
"unit_price": {
"value": 500,
"scale": 2,
"code": "USD"
},
"discount_total": {
"value": 0,
"scale": 2,
"code": "USD"
},
"void_total": {
"value": 0,
"scale": 2,
"code": "USD"
},
"discounted": false
}
],
"guest_count": "42",
"voided": false,
"sys_version": 4,
"sys_created_at": "2018-03-26T23:00:30.351Z",
"sys_created_by": "admin",
"sys_type_version": 3,
"sys_modified_at": "2018-03-27T12:24:00.269Z",
"sys_modified_by": "admin",
"sys_id": "5ab97b8f9534036231f8b72a"
}
PosCheckItem are only queryable via PosCheck.
PosCheckItem
The items that make up a transaction. Items listed here roll into PosCheck.
- Item_code - The given POS ID for the item.
- Unit_price - The menu price of the check item.
- Quantity - The amount of the item on the transaction.
- Sales_category - The sales category assigned to the item.
- Net_total - The total dollar amount of the item on the check without taxes or coupons applied to it.
- Gross_total - The total dollar amount of the item on the check with taxes and coupons applied to it.
- Tax_total - The total amount of taxes.
- Discount_total - The total amount of discounts that have been applied to the check.
- Void_total - If the check was voided this is its total.
- Voided - Whether or not the check was voided.
- Discounted - whether or not the check was discounted.
- PosVolumeItem - A dynamic driver that can represent things like guest counts, entree counts, and table counts.
- Datetime - The date that the amount being presented was captured.
- Amount - The total amount being presented by the driver.
- Volume_type - The type of volume that is being displayed.
- Revenue_center - The revenue center that data is being pulled from.
- Employee_reference - The point of sale ID given to the employee whose data you are viewing.
Example: To get a count of a number of items
EXAMPLE JSON RESPONSE:
[
{
_id: "55136",
count: 630
}
]
Example: How many items sold over a time period
EXAMPLE JSON RESPONSE:
[
{
_id: {
items: "55136",
business_day: "2018-04-01"
},
count: 26
},
{
_id: {
items: "55136",
business_day: "2018-04-02"
},
count: 17
}
]
Sending Canonical Data Over the REST API
In order to send data into the Clarifi ecosystem, your application will need to construct StoreInfo and StoreBusinessDay files and pass them over a RESTful endpoint to a particular location within your namespace, at which point those files will be parsed out and made available via the API.
Files? I Just Want to GET and SET!
In order to understand how to upload data into the REST API, we have to introduce a new term. A job is a webservice within your namespace assigned to a particular store that can perform a particular function, either on an event-based schedule or on a user-configured timer. Jobs can perform many functions within your namespace, such as calling to a variety of endpoints and packaging up the results, populating a UI for an end user to interact with, or flushing data that is no longer needed.
Clarifi applications are powered by jobs that run on the backend and move data throughout the ecosystem. As mentioned, jobs can either run on a schedule, or based on events. The Bodhi REST API utilizes SQS, a tool that allows applications to generate messages that other applications can listen for in order to know when to activate. For more information, check out this link: https://aws.amazon.com/sqs/.
Here’s how our POS integrations work: Our Agent application generates raw data from the machine and sends it up into the namespace in a “raw” bucket. The act of a new file landing in the raw bucket generates an SNS message. A “transform” job is listening for that SNS message, and so upon receiving it, it activates, running its service to transform the raw data into Canonical data and make it available via our API server. Upon completion of the job, the files are now placed in a “processed” bucket, generating a new SNS message. Other applications listening for that SNS message now know to activate.
That means that you can just GET and SET data over our API, however you’d be doing it here:
Only applications that run on timers would be able to access this data. A job that calls to the PosPunch endpoints every 30 minutes for example, would work just fine. However, a job that is listening for the SNS message (for example, to alert that the availability of a particular menu item has dropped below an acceptable threshold) would have no way of knowing your data is there.
Therefore, you need to introduce your data into the ecosystem earlier in the chain:
By doing this, you can be assured that Clarifi applications will be empowered to consume your data properly and thus provide value to your customers!
What’s Airwaves?
Airwaves is a job that you will need to install on your namespace that will listen for raw StoreInfo and StoreBusinessDay files that you POST into your namespace, parsing the data within, moving it through the API server, and generating an SNS message for downstream applications.
To install Airwaves, you’ll need to go to the Bodhi Shop. The Bodhi Shop is a place within your namespace where you can install and configure a variety of jobs and applications. Here’s a link: https://tools.hotschedules.io/shop/#/all?appType=job Find Airwaves from the list of available jobs and install.
The File Upload endpoint is special type that allows a user to upload files (StoreInfo and StoreBusinessDay) to be consumed by Clarifi Applications.
File Upload EndPoint URL: https://files.hotschedules.io/files/raw/store_id/filename
What you’ll need:
- A namespace running the Airwaves job
- Your files (StoreInfo and StoreBusinessDay)
- Method to pass data to the API (HS Bodhi Query Tool or Postman for example)
At a minimum, your file needs to include a full business day of data. For example, if you are posting sales at 10:00am and then again at 11:00am, your 11:00am file needs include all the data you posted at 10:00am as well as the data from 10:00am to 11:00am.
Login to your namespace: https://tools.hotschedules.io
Install the Airwaves app: Login to your namespace and use the Bodhi Shop to install the Airwaves App. This app is required to consume the files you will POST later in this example and enable Clarifi to consume the data for the apps within Clarifi.
Once installed, Airwaves will be available in the Job Manager.
You’re ready to start posting data to Clarifi.
To POST data into Clarifi, you will need to create 2 files and upload those to File Upload endpoint. When the files are received, Airwaves listens for those files, consumes them and transforms them into Canonical data for consumption by Clarifi applications.
Note: You will create a separate zip file for each file as you will POST each file separately when you submit your call to upload data into Clarifi. Attached are the file spec for each file type and further in this example, completed example files are provided for download.
Download StoreInfo.json File Spec
Download StoreBusinessDay.json File Spec
We have created a Postman collection to enable you to test posting data to the POS Canonical Service. The Collection includes examples for validating the JSON data in your StoreInfo and StoreBusinessDay files and POSTing to the File Upload Endpoint. The examples are titled “Validate StoreInfo”, “Validate StoreBusinessDay”, “StoreInfo” and “StoreBusinessDay”.
Select the “Run In Postman” button below to open the collection in Postman to start testing.
To validate your JSON data to ensure it’s well formed before you create your files, you can POST the data to the “validate” endpoint and receive a JSON repsonse upon success or failure.
Validate Endpoint URL: https://api.hotschedules.io/namespace/validate/StoreInfo or StoreBusinessDay
The following is an example of a Success message.
{ “valid”: true, “sys_type_version”: “1” }
The example provided below has been created using Postman. Configure Postman using the following example to POST your file to the API.
Configure Header
Configure Body
The configuration will enable you to pass in your bearer token and namespace, and do a PUT to https://files.hotschedules.io/files/raw/store_id/filename
You’ll be passing in a .zip file that contains your data, and attach the zip as part of the body. Postman will show a success message.
EXAMPLE JSON RESPONSE:
[
{
"namespace": "theposthatrefreshes",
"name": "StoreInfo6.zip",
"original_name": "StoreInfo6.zip",
"location": "theposthatrefreshes/5a997e4a490d05496aae228b/StoreInfo6.zip",
"media_type": "application/zip",
"uploaded_at": "2018-04-03T22:11:27.725Z",
"bucket": "raw",
"BodhiAsyncStatus": "/theposthatrefreshes/resources/BodhiAsyncStatus/5ac3fc0ff4a7c05f0ead361b"
}
]
Your files will be visible in your File Manager.
Once the file arrives in the namespace, the Airwaves job will activate and Airwaves will put the file through the API server, basically unpacking all the data within the file and making it available for other applications to consume.
The following example files (StoreInfoMMDDYR.json and StoreBusinessDayMMDDYR.json) are provided for download.
Best Practice: Name your json file and your zip file using a simliar naming convention.
i.e. StoreInfo040418.json and StoreInfo040418.zip
Working with HotSchedules Labor and Schedule Data
So far we have been focusing on interacting with POS data. However, perhaps you want to interact with labor or schedule data that has been generated within HS Labor. HS Labor offers a SOAP API that returns a variety of data, and the Bodhi REST API offers a proxy of those endpoints. This basically means that instead of having to change your calls to use (for example): https://soap.hotschedules.com/ws/getStoreEmployees (not a real URL)
You can use the REST API’s URL and auth mechanism:
https://api.hotschedules.io/namespace/services/hotschedules/concept_id/store_id/getStoreEmployees (not a real URL)
In order to utilize the HS SOAP proxy, you will need to acquire HS SOAP credentials and put them in a tool called the BodhiUserKeychain. Luckily, these credentials do not expire, so doing this once will set you up for life.
Follow these simple setup steps before proceeding.
Step 1: Obtain your API credentials from HotSchedules if you have not already done so.
Step 2: Login into the Account Manager
Step 3: In the upper right corner, select the wrench icon, then keychain, then your namespace.
Step 4: Enter your API credentials as provided by hotSchedules and click save.
Step 5: Continue with the example below to retrieve your token.
Making a call
Please Note: Through our standard service offering, HotSchedules will support up to 100 calls per hour, per store with bursts not to exceed 20 calls per minute per store. At this service level, the API will have a rate limit and status code 429 will return for calls beyond those limits.
The HotSchedules REST API supports all the standard REST verbs.
GET
POST
PUT
PATCH
DELETE
You can access these verbs for each of the types in the HotSchedules system. When an organization is created in the HotSchedules Platform, the organization automatically gets 32 ‘types’ that will store standard information and data about your organization. Those 'types’ can be viewed and reviewed at https://api.hotschedules.io/apidocs/index.html
GET
As an example, let’s do a GET on a store via CURL
curl -ik --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=platform" -X GET https://api.hotschedules.io/bodhi-social/resources/Store
This call will return the information about a store that’s been created for the bodhi-social organization
[{"sys_version":1,"image_url":"https://upload.wikimedia.org/wikipedia/commons/5/54/Golden_Gate_Bridge_0002.jpg","sys_type_version":12,"address":{"street_address":"555 Mission","extended_address":"","locality":"San Francisco","region":"CA","postal_code":"94111","country":"US"},"store_hours":[{"days":[7,1],"start":"0500","end":"0000"},{"days":[1,2],"start":"1200","end":"0200"},{"days":[2,3],"start":"1200","end":"0200"},{"days":[3,4],"start":"1200","end":"0200"},{"days":[4,5],"start":"1200","end":"0200"},{"days":[5,6],"start":"1200","end":"0200"},{"days":[6,7],"start":"0500","end":"0000"}],"sys_created_by":"admin__bodhi-social","sys_created_at":"2016-05-21T15:37:15.560Z","name":"platformstore","store_number":"1","display_name":"Platform Store","sys_id":"574080abb9a19e2dadee775b"}]
You can also get the JSON payload by navigating directly to this URL https://api.hotschedules.io/bodhi-social/resources/Store
You can create your own store for your organization either by executing a POST command (see below) to https://api.hotschedules.io/<organization_name>/resources/Store
or using our store manager tool at https://hotschedules.io/store-manager
. Either way, a store is a critical anchor for information in the Platform.
Next let’s look up a sale for our store in bodhi-social
curl -ik --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=platform" -X GET https://api.hotschedules.io/bodhi-social/resources/SalesTransaction
RESULT:
[{"order_number":10184,"item_count":1,"store_id":"574080abb9a19e2dadee775b","employee":{"id":"5151","name":"Ted Morrison"},"business_day":"2016-05-20","revenue_center":{"id":"2","name":"Restaraunt"},"type":{"id":"4","name":"1"},"timestamp":"2016-05-21T03:34:00.000Z","transaction_id":"557605fc4c32e071180a46042016-05-2010184","net_total":{"value":325,"code":"USD","scale":2},"discount_total":{"value":0,"code":"USD","scale":2},"tax_total":{"value":23,"code":"USD","scale":2},"gross_total":{"value":348,"code":"USD","scale":2},"tender_total":{"value":348,"code":"USD","scale":2},"order_opened_at":"2016-05-21T03:33:00.000Z","order_closed_at":"2016-05-21T03:34:00.000Z","guest_count":1,"sys_version":1,"sys_created_at":"2016-05-21T16:02:30.800Z","sys_created_by":"admin__bodhi-social","sys_type_version":12,"sys_id":"574086965eacd06aa3db036b"}]
We can also look up our Store using query parameters in our URL
curl --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=platform" 'https://api.hotschedules.io.io/bodhi-social/resources/SalesTransaction?where=%7Bbusiness_day:"2016-05-20"%7D&fields=business_day'
OR alternatively:
curl -g --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=platform" 'https://api.hotschedules.io/bodhi-social/resources/SalesTransaction?where={business_day:"2016-05-20"}&fields=business_day'
RESULT:
[{"order_number":10184,"item_count":1,"store_id":"574080abb9a19e2dadee775b","employee":{"id":"5151","name":"Ted Morrison"},"business_day":"2016-05-20","revenue_center":{"id":"2","name":"Restaraunt"},"type":{"id":"4","name":"1"},"timestamp":"2016-05-21T03:34:00.000Z","transaction_id":"557605fc4c32e071180a46042016-05-2010184","net_total":{"value":325,"code":"USD","scale":2},"discount_total":{"value":0,"code":"USD","scale":2},"tax_total":{"value":23,"code":"USD","scale":2},"gross_total":{"value":348,"code":"USD","scale":2},"tender_total":{"value":348,"code":"USD","scale":2},"order_opened_at":"2016-05-21T03:33:00.000Z","order_closed_at":"2016-05-21T03:34:00.000Z","guest_count":1,"sys_version":1,"sys_created_at":"2016-05-21T16:02:30.800Z","sys_created_by":"admin__bodhi-social","sys_type_version":12,"sys_id":"574086965eacd06aa3db036b"}]
So https://api.hotschedules.io/bodhi-social/resources/SalesTransaction?where={%27business_day%27:%272016-05-20%27}
would return all SalesTransaction’s for the business day of 2016-05-20.
The URL https://api.hotschedules.io/bodhi-social/resources/SalesTransaction?where={%27store_id%27:%27574080abb9a19e2dadee775b%27}
would return all SalesTransaction’s for the store 574080abb9a19e2dadee775b (our Platform test store).
All Types can be queried by any parameter within the type using a ?where={} clause. It’s EXTREMELY important for efficiency and performance to query using indexes on your types. You can review the Types for your organization as well as the Indexes and Parameters by using our free Type Tool located at https://tools.hotschedules.io/types
or by inspecting https://api.hotschedules.io/<organization_name>/resources/BodhiType
POST
To POST to a type you need to add the the header: 'Content-Type: application/json’ to your cURL Command
curl -ik -H 'Content-Type: application/json' --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=foo" -X POST -d '{
"store_id": "l8zeL",
"business_day": "2016-05-13",
"timestamp": "2016-05-12T05:58:31.296Z",
"transaction_id": "FGHG012",
"tender_total": {
"code": "USD",
"scale": 2,
"value": 620
}
}' https://api.hotschedules.io/<organization_name>/resources/SalesTransaction
That command will post the json object to the SalesTransaction type. You can now GET on this type either using cURL or the free query tools available at https://tools.hotschedules.io/query
Bulk Post
All bulk operations are accessible through https://api.hotschedules.io
The size limitation for the body is 17MB
Syntax:
POST /<organization_name>/bulk
with json body
{
"config": {
"op": "insert" or "update" or "upsert" or "invite", * see below
"report": true, <- optional, need a report? (default false)
"target": "target_name” <- the name of the type (not for invite)
},
"payload": [{
"the_field": "my first thing to insert or upsert or invite",
"other_field": "the_other_field"
}, {
"the_field": "my second thing to insert or upsert",
"other_field": "the_other_field2"
}]
}
The payload varies depending on the type of operation and Returns 202 with header bulk_id:<the bulk id>
The result of a report, if requested, is accessible as soon as the processing is done on:
GET /<organization_name>/bulk/<bulk_id>
RESPONSE:
returns 200 with a json array body where the order of the cells matches the order of the payload. The report can be accessed only once.
returns 204 if the report is not ready yet
returns 404 if no report was found with that id
- update/upsert is only available for types not encapsulated
- insert on system types only BodhiUser, BodhiType and BodhiEnumeration and any not encapsulated type
Example:
{
"config": {
"op": "insert",
"report": true,
"target": "BulkTest"
},
"payload": [{
"name": "leo",
"other_field": "mauris non"
}, {
"name": "orci",
"other_field": "sit amet justo"
}, {
"name": "nulla",
"other_field": "pulvinar sed nisl nunc rhoncus"
}, {
"name": "nulla",
"other_field": "diam cras"
}, {
"name": "est",
"other_field": "dui nec nisi volutpat"
}, {
"name": "lorem",
"other_field": "cursus id"
}, {
"name": "molestie",
"other_field": "potenti nullam porttitor lacus at"
}, {
"name": "sapien",
"other_field": "ultrices aliquet maecenas leo"
}, {
"name": "nibh",
"other_field": "consectetuer eget rutrum at"
}, {
"name": "luctus",
"other_field": "nisl nunc"
}]
}
PUT
The HTTP verb PUT can be used on any type as long as there’s a unique index on the field or fields. You can always PUT on sys_id
As an example, in the above SalesTransaction example, the sys_id is 574086965eacd06aa3db036b, a PUT to the SalesTransaction based on sys_id would be as follows:
curl -ik -H 'Content-Type: application/json' --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=foo" -X PUT -d '{ "store_id": "l8zeL", "business_day": "2016-05-13", "timestamp": "2016-05-12T05:58:31.296Z", "transaction_id": "FGHG012", "tender_total": { "code": "USD", "scale": 2, "value": 620 } }' https://api.hotschedules.io/tutorial/resources/SalesTransaction/574086965eacd06aa3db036b
PUT Upsert
Upsert is a safe way to replace an existing record, or POST a record if the entry does not currently exist.
You can upsert by appending your URL with ?upsert=true
As an example, the above PUT example can be changed to a replace by appending the ?upsert=true to the cURL command:
curl -ik -H 'Content-Type: application/json' --cookie "RUSK=8a6f98bb1033055fc04d644c0006789335f96c2b-username=foo" -X PUT -d '{ "store_id": "l8zeL", "business_day": "2016-05-13", "timestamp": "2016-05-12T05:58:31.296Z", "transaction_id": "FGHG012", "tender_total": { "code": "USD", "scale": 2, "value": 620 } }' https://api.hotschedules.io/tutorial/resources/SalesTransaction/574086965eacd06aa3db036b?upsert=true
PATCH
the HTTP verb PATCH will allow you to alter single parameters or fields within a record in your type. Patch commands follow the following sytax: [ { “op”: “replace”, “path”: “/baz”, “value”: “boo” }, { “op”: “add”, “path”: “/hello”, “value”: [“world”] }, { “op”: “remove”, “path”: “/foo”} ]
The HTTP verb PATCH can be used on any type as long as there’s a unique index on the field or fields. You can always PATCH on sys_id
DELETE
the HTTP verb DELETE will allow you to remove a record in your type. To delete multiple records, include a ?where={} in your URL to narrow or expand then number of records removed.
File Upload
The Platform BodhiFileUpload endpoints are special types that allow a user to upload and download any file (like a dbf file from your store’s POS).
Metadata of your file is posted to type BodhiFileUpload on successful upload
BodhiFileUpload example record:
{ "namespace": "bodhi", "original_name": "profile_pic5.jpg", "sys_version": 1, "location": "bodhi/profile_pic5.jpg", "uploaded_at": "2015-09-10T19:42:48+0000", "sys_created_by": "admin__bodhi", "sys_created_at": "2015-09-10T19:42:49+0000", "name": "profile_pic5.jpg", "media_type": "image/jpeg", "sys_id": "55f1dd39b9b5904f64c8212f" }
Examples:
The following are curl examples of how to specify file location in your upload/download/delete commands. Everything after “upload/” or “download/” in the url is used as the destination. Note that filename is always specified in the url.
curl -X POST -u <username>:<password> https://api.hotschedules.io/<organization_name>/controllers/vertx/upload/recipes/food/BurritoRecipe.txt -F "upload1=@THE_FILE"
curl -X PUT -u <username>:<password> https://api.hotschedules.io/<organization_name>/controllers/vertx/upload/recipes/food/BurritoRecipe.txt -F "upload1=@THE_FILE"
Download by path:
curl -X GET -u <username>:<password> https://api.hotschedules.io/<organization_name>/controllers/vertx/download/recipes/food/BurritoRecipe.txt
Download by sys_id:
curl -X GET -u <username>:<password> https://api.hotschedules.io/<organization_name>/controllers/vertx/download/56f9c2b4fa92ec27934a76ae
Delete a file:
curl -X DELETE -u <username>:<password> https://api.hotschedules.io/<organization_name>/controllers/vertx/upload/recipes/food/BurritoRecipe.txt
We have created a Postman collection to enable you with making calls to the REST API.
REST API Service
Introduction
The HotSchedules REST API provides a user-friendly way to obtain HS Data.
Please ensure that API access has been enabled for your HotSchedules account. Contact customer service 1-866-753-3853 for access or questions.
The url path can look like any of the following, depending on which type is being queried:
HTTP Status Codes provide a description of the sucess or failure of a call: https://httpstatuses.com
../hotschedules/<concept_id>/<store_id>/<type_method>?
../hotschedules/<concept_id>/<type_method>?
../hotschedules/<type_method>?
Available Methods
Note: Results are currently cached with a TTL of 60 minutes.
What is TTL? Time to live or hop limit is a mechanism that limits the lifespan or lifetime of data in a computer or network
getConcepts
This method returns a list of concepts for a company.
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/getConcepts"
Sample JSON response:
[
{
"extId": 3714,
"name": "HotSchedules"
}
]
Key | Type | Description |
---|---|---|
extId | Number | Concept external ID |
name | String | Concept Name |
getClientCertifications
This method takes in a concept ID and a store ID and returns client certification objects. It is meant to get a list of all certifications for that store.
The inputs of this method are the arguments defined by the following table.
Query parameter | Type | Description |
---|---|---|
Concept | Int | The identifier for the location’s concept. Must be unique within the company. Contact HotSchedules if you’re not sure about this value. |
storeNum | Int | Numeric (integer) identifier for the store. Must be unique within the concept. |
getEmployeeCertifications
This method takes in a concept ID, store ID and employee POS ID and returns an array of employee certificate objects. It is meant to get a list of all employee certification information for an employee for that store.
The inputs of this method are the arguments defined by the following table.
Query parameter | Type | Description |
---|---|---|
Concept | Int | The identifier for the location’s concept. Must be unique within the company. Contact HotSchedules if you’re not sure about this value. |
storeNum | Int | Numeric (integer) identifier for the store. Must be unique within the concept. |
empPOSId | Int | POS numeric employee ID. |
getLocations
This method takes in a concept ID and store ID. It returns an array of dataLocation objects, each of which represent one HotSchedules schedule location.
The inputs of this method are the arguments defined by the following table.
Query parameters | Type | Description |
---|---|---|
concept | int | The identifier for the location’s concept/group. Must be unique within the company. Contact HotSchedules if you’re not sure about this value. | storeNum | int | Numeric (integer) identifier for the location. Must be unique within the concept. |
The outputs of this method are the arguments defined by the following table.
Query parameter | Type | Description |
---|---|---|
return | dataLocationArray | Array of dataLocation objects. |
getDriversByInterval
This method will take a concept ID, store number, start and end dates, volume type, and data type and return a list of total driver amount for each interval in the date range requested for that concept, store and labor type.
Intervals are configured during initial setup for the customer and are typically 30 minutes or 15 minutes.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept |
startDate | hsSimpleDate | Start date for the range of data requested |
endDate | hsSimpleDate | End date for the range of data requested |
volumeType | driverClass | Classification of driver requested. Allowed types would be all of the classifications supported from API, HSC, or FTP integration. “Guests”, “Tables”, “Entrees”, “Deliveries”, “Transactions” and “Products” |
dataType | driverType | Type of driver requested. Allowed types are “ACTUAL”, “ADJ_FORECASTED”, and “PRE_ADJ_FORECASTED” |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getDriversByInterval?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016&volume_type=TABLE&data_type=ACTUAL"
Sample JSON response:
[
{
"companyExtRef": 264319,
"conceptExtRef": 3714,
"driverAmount": 0,
"driverClass": "TABLE",
"driverType": "ACTUAL",
"intervalEndDate": {
"day": 1,
"month": 10,
"year": 2017
},
"intervalEndTime": {
"hours": 0,
"militaryTime": true,
"minutes": 30,
"seconds": 0
},
"intervalStartDate": {
"day": 1,
"month": 10,
"year": 2017
},
"intervalStartTime": {
"hours": 0,
"militaryTime": true,
"minutes": 0,
"seconds": 0
},
"storeExtRef": 98
}
]
Key | Type | Description |
---|---|---|
driverAmount | Number | Quantity of driver for interval expressed in the record |
driverClass | String | Description of driver type supplied for the interval expressed in the record |
intervalStartTime | Object | The hour, minutes, and seconds corresponding to the start of the interval expressed in the record. Interval times are local to the store’s time zone |
intervalEndTime | Object | The hour, minutes, and seconds corresponding to the end of the interval expressed in the record. Interval times are local to the store’s time zone |
intervalStartDate | Object | The date corresponding to the start of the interval expressed in the record |
intervalEndDate | Object | The date corresponding to the end of the interval expressed in the record |
conceptExtRef | Number | The concept ID configured by HotSchedules for the concept of the store owning the data of the record., contact HotSchedules if Concept IDs need to be defined or configured |
storeExtRef | Number | The store ID configured within HotSchedules for the store owning the data of the record., contact HotSchedules if Store IDs need to be defined or configured |
companyExtRef | Number | The company ID defined by HotSchedules for the store owning the data of the record., contact HotSchedules if the Company ID needs to be defined. This ID cannot be customized or configured |
driverType | String | Type of driver requested. Allowed types are: “ACTUAL” - Corresponds to the actual values produced by the store. “ADJ_FORECASTED”- Corresponds to the final forecasted driver amount that the schedules were based off from for the driver. “PRE_ADJ_FORECASTED”- Corresponds to the original forecasted driver amount previous to any forecast adjustments |
getEmpAvailability
This method takes in a concept ID and a store ID and returns an array of wsEmpAvailability objects. It is meant to get a list of all employee availability for that store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept |
active_only | Boolean | Boolean that defines whether or not to include terminated employees in response |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getEmpAvailability?active_only=true"
Sample JSON response:
[
{
"availabilities": [
{
"dayName": "Sunday",
"dayNum": 1,
"parHoursMax": -1,
"parHoursMin": -1,
"parShiftsMax": -1,
"parShiftsMin": -1,
"partialBeforeAfter": null,
"partialTime": null,
"shiftId": 1582006201,
"shiftName": "AM",
"statusName": "Not Available",
"statusNum": 3
},
{
"dayName": "Sunday",
"dayNum": 1,
"parHoursMax": -1,
"parHoursMin": -1,
"parShiftsMax": -1,
"parShiftsMin": -1,
"partialBeforeAfter": null,
"partialTime": null,
"shiftId": 1582006202,
"shiftName": "PM",
"statusName": "Not Available",
"statusNum": 3
}
],
"empHrId": -1,
"empNum": 9801
}
]
Key | Type | Description |
---|---|---|
empNum | Number | Employee POS ID |
availabilities | Array | Returns an array of availability for an employee |
empHrId | Number | Employee HR ID |
getEmpInfo
This method takes in a concept ID and a store ID and returns an array of wsEmpInfo objects. It is meant to get a list of all employees for that store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
active_only | Boolean | Boolean that defines whether or not to include terminated employees in response. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getEmpInfo?active_only=true"
Sample JSON response:
[
{
"accountCreated": "2017-05-04T10:18:46.957-05:00",
"empHrId": -1,
"empNum": -1,
"lastUpdated": "2017-05-04T10:18:47.040-05:00",
"permissionSetName": "Default HotSchedules Employee"
},
{
"accountCreated": "2017-07-07T10:05:48.820-05:00",
"assignedSchedules": {
"extId": -1,
"hsId": 1050941698,
"name": "FOH"
},
"empHrId": -1,
"empNum": 9898,
"lastUpdated": "2017-10-13T13:59:36.523-05:00",
"permissionSetName": "Employee"
},
{
"accountCreated": "2017-05-04T10:18:46.817-05:00",
"empHrId": -1,
"empNum": -1,
"lastUpdated": "2017-07-07T10:00:20.487-05:00",
"permissionSetName": "Default HS Support User"
},
{
"accountCreated": "2017-10-13T12:48:57.903-05:00",
"assignedSchedules": {
"extId": -1,
"hsId": 1050941698,
"name": "FOH"
},
"empHrId": -1,
"empNum": 9801,
"lastUpdated": "2017-10-13T12:50:58.597-05:00",
"permissionSetName": "Employee"
}
]
Key | Type | Description |
---|---|---|
lastUpdated | String | Last time the employee record was updated |
accountCreated | String | Date/time the account was created |
permissionSetName | String | Permission set name assigned to the employee |
empNum | Number | Employee POS ID |
assignedSchedules | Array | The schedule in which the employee is assigned. Array contains extId, hsId and name |
empHrId | Number | Employees HR ID |
getEmpJobs
This method takes in a concept ID and a store ID and returns an array of wsEmpJob objects. It is meant to get a list of all jobs assigned to all employees for that store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getEmpJobs?active_only=true"
Sample JSON response:
[
{
"clientId": 25124840,
"hsEmpId": 587378309,
"hsJobId": 27134060,
"ovtWage": 22.5,
"posEmpId": 9898,
"posJobId": 1099,
"primary": true,
"regWage": 15,
"storeNum": 98
}
]
Key | Type | Description |
---|---|---|
hsJobId | Number | HotSchedules internal job code ID |
clientId | Number | Unique identifier for client provided via HotSchedules |
regWage | Number | Regular hourly wage rate for employee |
posEmpId | Number | POS numeric ID for employee |
hsEmpId | Number | HotSchedules internal employee account ID |
storeNum | Number | Unique numeric store ID within HotSchedules, generally set up to mirror the client internal store IDs |
ovtWage | Number | Overtime hourly wage rate for employee |
posJobId | Number | POS numeric ID for the job code |
primary | Boolean | Boolean flag to designate if the job code is the primary job for the employee |
getGroups
This method takes in a concept ID and returns group information for the concept.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/getGroups"
Sample JSON response:
[
{
"conceptExtId": 3714,
"extId": 0,
"name": "My Group Name"
}
]
Key | Type | Description |
---|---|---|
conceptExtId | Number | Concept external ID |
extId | Number | Group external ID |
name | String | Group name |
getGuestCounts
This method will take a concept ID, store number, start and end dates and return a list of guest counts for the date range requested.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start | dateTime | Start date for the range of data requested. This is a basic dateTime object. |
end | dateTime | End date for the range of data requested. This is a basic dateTime object. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getGuestCounts?start_date=2016-04-30T00:00:00&end_date=2016-05-03T00:00:00"
Sample JSON response:
[
{
"businessDate": "2017-02-05T00:00:00-06:00",
"dateTime": "2017-02-05T05:41:00-06:00",
"guestCount": 8,
"rvcExtId": 1
},
{
"businessDate": "2017-03-05T00:00:00-06:00",
"dateTime": "2017-03-05T05:41:00-06:00",
"guestCount": 18,
"rvcExtId": 1
}
]
Key | Type | Description |
---|---|---|
businessDate | String | Business date of transaction |
dateTime | String | Date time of the transaction |
guestCount | Number | Number of guests for the transaction |
rvcExtId | Number | Represents the numeric revenue center ID associated with the guest |
getLaborByBusDay
This method will take a concept ID, store number, start and end dates and a labor type and return a list of total labor by job code for each interval in the date range requested for that concept, store and labor type.
Intervals are configured during initial setup for the customer and are typically 30 minutes.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept |
start | hsSimpleDate | Start date for the range of data requested |
end | hsSimpleDate | End date for the range of data requested |
laborType | laborType | Type of labor requested. Allowed types are “optimal”, “forecasted” and “scheduled”. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getLaborByBusDay?start_day=30&start_month=1&start_year=2016&end_day=5&end_month=5&end_year=2016&labor_type=optimal"
Sample JSON response:
[
{
"interval": {
"intervalDate": {
"day": 1,
"month": 2,
"year": 2016
},
"intervalTime": {
"hours": 0,
"militaryTime": true,
"minutes": 0,
"seconds": 0
},
"laborType": "forecasted",
"volume": 0
}
}
]
Key | Type | Description |
---|---|---|
intervalDate | Object | Date expressed in the record |
intervalTime | Object | The hour, minutes, and seconds expressed in record |
laborType | String | Type of labor requested. Allowed types are “optimal”, “forecasted” and “scheduled”. |
volume | String | Number of employees based on demand at that interval |
getLaborByJobAndInterval
This method will take a concept ID, store number, start and end dates and a labor type and return a list of total labor by job code for each interval in the date range requested for that concept, store and labor type.
Intervals are configured during initial setup for the customer and are typically 30 minutes.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start | hsSimpleDate | Start date for the range of data requested |
end | hsSimpleDate | End date for the range of data requested |
laborType | laborType | Type of labor requested. Allowed types are “optimal”, “forecasted” and “scheduled”. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getLaborByJobAndInterval?start_day=30&start_month=1&start_year=2016&end_day=5&end_month=5&end_year=2016&labor_type=optimal"
Sample JSON response:
[
{
"interval": {
"intervalDate": {
"day": 1,
"month": 2,
"year": 2016
},
"intervalTime": {
"hours": 12,
"militaryTime": true,
"minutes": 0,
"seconds": 0
},
"laborType": "scheduled",
"volume": 0
}
}
]
Key | Type | Description |
---|---|---|
intervalDate | Object | Date expressed in the record |
intervalTime | Object | The hour, minutes, and seconds expressed in record |
laborType | String | Type of labor requested. Allowed types are “optimal”, “forecasted” and “scheduled”. |
volume | String | Number of employees based on demand at that interval |
getSalesItemsV3
This method takes in a concept ID, store ID, start and end dates.It returns an array of sales for that store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start | hsSimpleDate | First day of projected sales requested. This is an hsSimpleDate object. |
end | hsSimpleDate | Last day of projected sales requested. This is an hsSimpleDate object. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getSalesItemsV3?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016"
Sample JSON response:
[
{
"clientId": 1234567,
"empId": 7,
"extId": -3,
"rvc": 1,
"rvcName": "TAKE OUT",
"salesCat": 1,
"storeNum": 13,
"ttl": 7.99,
"businessDate": {
"day": 30,
"month": 4,
"year": 2016
},
"transDate": {
"day": 30,
"month": 4,
"year": 2016
},
"transTime": {
"hours": 7,
"militaryTime": true,
"minutes": 33,
"seconds": 0
}
}
]
Key | Type | Description |
---|---|---|
clientId | Object | Business Date information, Day, Months and Year |
empId | Array | Array of the day part total. Start Time and End Time |
extId | Number | Optional-Unique transaction ID for the sales item |
rvc | Number | Revenue center |
rvcName | String | Name for the revenue center associated with the location within the restaurant |
salesCat | Number | Sales category |
storeNum | Number | Store number |
ttl | Number | Total sales for the sales category |
businessDate | Object | Business Date information, Day, Months and Year |
transDate | Object | Transaction data |
transTime | Object | Transaction time |
getProjectedSalesV3
This method will take a concept ID, store number, start and end dates. This method uses hsSimpleDate objects for dates and hsSimpleTime objects for times.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start | hsSimpleDate | First day of projected sales requested. This is an hsSimpleDate object. |
end | hsSimpleDate | Last day of projected sales requested. This is an hsSimpleDate object. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getProjectedSalesV3?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016"
Sample JSON response:
[
{
"businessDate": {
"month": 4,
"year": 2016,
"day": 30
},
"dayPartTotals": [
{
"summaryItemTotals": {
"summaryItemTotal": 5246.26,
"summaryItemName": "Take out Drive through"
},
"dayPartEndTime": {
"hours": 4,
"seconds": 0,
"amPm": "pm",
"militaryTime": true,
"minutes": 0
},
"dayPartName": "Evening",
"dayPartTotal": 5246.26,
"dayPartStartTime": {
"hours": 18,
"seconds": 0,
"amPm": "am",
"militaryTime": true,
"minutes": 0
}
}
],
"dateTotal": 9934.779
}
]
Key | Type | Description |
---|---|---|
businessDate | Object | Business Date information, Day, Months and Year |
dayPartTotals | Array | Array of the day part total. Start Time and End Time |
dateTotal | Number | Total projected sales for the day part |
getRCVs
Revenue center information defined for a group.
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getRCVs"
Sample JSON response:
[
{
"revenueCenterName": "Take Out",
"extId": 0,
"groupLevel": true
},
{
"revenueCenterName": "Drive Thru",
"extId": 1,
"groupLevel": true
},
{
"revenueCenterName": "Beverage",
"extId": 2,
"groupLevel": true
}
]
Key | Type | Description |
---|---|---|
revenueCenterName | String | Revenue center name |
extId | Number | Revenue center ID |
groupLevel | Boolean | Indicates if the revenue center was created at a group level |
getSalesCats
This method takes in a concept ID and a store ID and returns an array of sales categories for that store. Sales categories will typically establish what kind of item was sold: Food, Beverage, Alcohol, Merchandise.Sales categories can be local to a particular store, or defined in HotSchedules as belonging to an entire group (called group-level sales categories).
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getSalesCats"
Sample JSON response:
[
{
"salesCategoryName": "Beverages",
"extId": 1,
"groupLevel": true
}
]
Key | Type | Description |
---|---|---|
salesCategoryName | String | Name of the sales category |
extId | Number | External ID associated with the category |
groupLevel | Boolean | Indicates if the revenue center was created at a group level |
getScheduleV3
This method takes in a concept ID, store ID, start and end dates. It returns an array of WSScheduleItem3 objects, which represent one scheduled shift each, for import into the POS. This method returns the same data as getSchedule, plus extended scheduled shift data, including location ID, regular pay rate, OT pay rate, scheduled regular minutes, scheduled OT minutes (if any), scheduled special pay (if any) and the unique schedule ID, internal to HS.This method uses hsSimpleDate objects for dates. Note that the date referenced is the calendar date and not the business date.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start | hsSimpleDate | First day of scheduled shifts you are requesting. This method uses hsSimpleDate objects for dates. |
end | hsSimpleDate | Last day of scheduled shifts you are requesting. This method uses hsSimpleDate objects for dates. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getScheduleV3?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016"
Sample JSON response:
[
{
"inDate": {
"month": 5,
"year": 2016,
"day": 2
},
"inTime": {
"hours": 9,
"seconds": 0,
"militaryTime": true,
"minutes": 0
},
"outDate": {
"month": 5,
"year": 2016,
"day": 2
},
"outTime": {
"hours": 18,
"seconds": 0,
"militaryTime": true,
"minutes": 0
},
"jobHsId": 1111111,
"payRate": 1,
"specialPay": 0,
"empHSId": 222222,
"ovtMinutes": 0,
}
]
Key | Type | Description |
---|---|---|
outDate | Object | Schedules out date |
jobHsId | Number | HotSchedules internal job code ID |
payRate | Number | Regular hourly pay rate for employee |
inDate | Object | Scheduled in date |
specialPay | Number | Special Pay amounts |
empHsId | Number | HotSchedules internal employee account ID |
ovtMinutes | Number | Total Overtime Minutes for employee |
inTime | Object | Scheduled in time |
outTime | Object | Scheduled out time |
getShiftsV3
This method takes in a concept ID, store ID, start and end dates and three flags (isHouse, isScheduled and isPosted). It returns an array of WSScheduleItem3 objects, which represent one scheduled shift each. What shifts are returned depends on the flags set:
- isHouse - includes scheduled or posted shifts that are not assigned to an employee (called ‘house shifts’ in HotSchedules).
- isScheduled - includes shifts that are in schedules that have been saved in HotSchedules, but might not have been posted.
- isPosted - includes shifts that are in schedules that have been set to the 'posted’ status within HotSchedules.
This method returns extended scheduled shift data, including location ID, regular pay rate, OT pay rate, scheduled regular minutes, scheduled OT minutes (if any), scheduled special pay (if any) and the unique schedule ID, internal to HS.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
isHouse | Boolean | Include house shifts? These are shifts which were never assigned to someone on a schedule, or were once assigned but removed from an employee when their status, job, etc. changed. |
isScheduled | Boolean | Include scheduled shifts? These are shifts which are on a schedule that has been saved in HotSchedules, but might not have been posted |
isPosted | Boolean | These are shifts that are in schedules that have been set to the 'posted’ status within HotSchedules. |
jobCodes | IntArray | Integer array of job codes to be included in this method’s return. if this parameter is null or empty, all jobs will be included. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getShiftsV3?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016&is_house=true&is_scheduled=true&is_posted=true"
Sample JSON response:
[
{
"empHSId": -1,
"empPosId": -1,
"jobHsId": 786323133,
"jobPosId": 11,
"inDate": {
"day": 5,
"month": 5,
"year": 2016
},
"outDate": {
"day": 5,
"month": 5,
"year": 2016
},
"inTime": {
"hours": 9,
"militaryTime": true,
"minutes": 0,
"seconds": 0
},
"outTime": {
"hours": 16,
"militaryTime": true,
"minutes": 0,
"seconds": 0
},
"weekStart": {
"day": 2,
"month": 5,
"year": 2016
},
"weekEnd": {
"day": 8,
"month": 5,
"year": 2016
},
"locationId": 787124196,
"scheduleId": 781691586,
"payRate": 0,
"ovtRate": 0,
"ovtMinutes": 0,
"regMinutes": 420,
"specialPay": 0
}
]
Key | Type | Description |
---|---|---|
empHsId | Number | HotSchedules internal employee account ID |
empPosId | Number | POS numeric Employee ID |
jobHsId | Number | HotSchedules internal job code ID |
jobPosId | Number | POS job code ID |
inDate | Object | Scheduled in date |
outDate | Object | Schedules out date |
inTime | Object | Scheduled in time |
outTime | Object | Scheduled out time |
weekStart | Object | Start date of the work week |
weekEnd | Object | End date of the work week |
locationId | Number | Location ID |
scheduleId | Number | Schedule ID |
payRate | Number | Regular hourly pay rate for employee |
ovtRate | Number | overtime pay rate |
ovtMinutes | Number | Total overtime minutes for employee |
regMinutes | Number | total regular minutes for employee |
specialPay | Number | Special Pay amounts |
getStoreEmployees
This method takes in a concept ID, store ID, a flag to determine if only active employees are returned, and returns an array of WSEmployee objects.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
active_only | Boolean | Boolean that defines whether or not to include terminated employees in response. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getStoreEmployees?active_only=true"
Sample JSON response:
[
{
"zipCode": 12345,
"hireDate": "2016-11-03T10:16:38.533-05:00",
"address": "111 Addy Way",
"clientId": 87654321,
"LName": "Lockman",
"address2": "Unit 3",
"city": "Austin",
"mobile": "(222) 222-2222",
"NName": "Jay",
"altId": -1,
"FName": "Harrison",
"empNum": -1,
"phone": "(333) 333-3333",
"hsId": 987654321,
"dob": "1981-09-16T00:00:00-05:00",
"state": "TX",
"storeNum": 3,
"email": "harrison.lockman@email.com",
"status": 1
}
]
Key | Type | Description |
---|---|---|
zipCode | Number | Zip Code |
hireDate | String | Employee Hire Date |
address | String | Employee Address line 1 |
clientId | Number | Unique identifier for client provided via HotSchedules |
LName | String | Employee Last Name |
address2 | String | Employee Address line 2 |
city | String | City field for Address |
mobile | String | Employees Mobile Phone |
NName | String | Employee Nickname |
altId | Number | Employee HR ID. This must be a unique value across the company. It is used for HotSchedules Shared Employees. |
FName | String | Employee First Name |
empNum | Number | Employee POS ID |
phone | String | Phone Number |
hsId | Number | HS unique ID of an employee that is assigned at the time the employee is created in HS. This number is not configurable but automatically assigned. This number can be obtained through the get method and is an option to include in the set. However this is not necessary |
dob | String | Date of birth |
state | String | State |
storeNum | Number | Unique numeric store ID within HotSchedules. Generally set up to mirror the client internal store IDs. |
String | Employee’s email address | |
status | Number | Active = 1, Inactive = 0, Terminated = -1 |
getStoreJobs
This method takes in a concept ID and a store ID, and returns an array of all jobs currently defined in HotSchedules for the given concept/store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getStoreJobs"
Sample JSON response:
[
{
"jobName": "Manager",
"posId": 11,
"clientId": 14935376,
"hsId": 786323133,
"defRate": 0,
"storeNum": 3
}
]
Key | Type | Description |
---|---|---|
jobName | String | Name for Job Code |
posId | Number | Numeric POS ID for Job Code |
clientId | Number | Unique identifier for client provided via HotSchedules |
hsId | Number | HS unique ID of an employee that is assigned at the time the employee is created in HS. This number is not configurable but automatically assigned. This number can be obtained through the get method and is an option to include in the set. However this is not necessary |
defRate | Number | Default Pay Rate for a Job Code |
getStoresV2
Returns information about the stores within a group.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
group_id | Number | Group in which the store is assigned |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/getStoresV2?group_id=0"
Sample JSON response:
[
{
"groupName": "HS Grill",
"active": true,
"groupExtId": 1,
"storeName": "Sales Demo - Bug Test",
"storeNum": -1,
"city": "Fremont",
"postalCode": "94555",
"stateProvince": "CA",
"streetAddress1": "1 st. address",
"streetAddress2": "Unit 3",
"timeZone": "US/Central"
}
]
Key | Type | Description |
---|---|---|
groupName | String | Name of the group |
active | Boolean | Indicates if the store is active |
groupExtId | Number | The external ID for the store |
storeName | String | The name of the store |
storeNum | Number | Unique numeric store ID within HotSchedules. Generally set up to mirror the client internal store IDs. |
city | String | City |
postalCode | Number | Zip code / postal code |
stateProvince | String | State province |
streetAddress1 | String | Main street adress |
streetAddress2 | String | Apartment number, Suite, Unit, etc.. |
timeZone | String | Store timezone |
getTimeCards
This method takes in a concept ID, store ID, start and end dates. It returns an array of wsTimeCard3 objects, which represent one employee time card each. Each time card has information for one employee punch record, including business date, regular and OT minutes and wages, clock in and clock out times. If this store is using HotSchedules’ web-based timeclock for employee clock-in, any open punches in the date range are also included in the response.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getTimeCards?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016"
Sample JSON response
[
{
"jobName": "Bartender",
"ovtTtl": 0,
"ovtHrs": 0,
"clockOut": "2016-05-01T23:48:00-05:00",
"regWage": 0,
"clockIn": "2016-05-01T16:36:00-05:00",
"ovtWage": 7.5,
"breakMinutes": 0,
"jobExtId": 18,
"jobId": -1,
"businessDate": {
"month": 5,
"year": 2016,
"day": 1
},
"regHrs": 7.2,
"spcTtl": 7.25,
"hsId": 929931332168,
"spcHrs": 0,
"ovtMins": 0,
"extId": -2005922,
"storeNum": 3,
"empPosId": 2068,
"regTtl": 0
}
]
Key | Type | Description |
---|---|---|
jobName | String | POS job code name |
ovtTtl | Number | Optional-Overtime total pay amount |
ovtHrs | Number | Optional-Overtime hours in shift |
clockOut | String | Clock out timestamp for the shift |
regWage | Number | Regular hourly pay rate |
clockIn | String | Clock in timestamp for the shift |
ovtWage | Number | Optional-Overtime hourly pay rate |
breakMinutes | Number | Number of non-paid break minutes in shift |
jobId | Number | POS numeric identifier for the job |
jobExtId | Number | POS numeric Job Code ID |
businessDate | Array | Business Date information, Day, Months and Year |
regHrs | Number | Regular hours represented in shift |
spcTtl | Number | Optional-Special Pay total pay amount |
hsId | Number | Optional-Internal HotSchedules employee Account ID. Not required, will be set by the service. |
spcHrs | Number | Optional-Special Pay Hours |
ovtMins | Number | Optional-Overtime minutes in shift |
storeNum | Number | Unique numeric store identifier. Generally set up to mirror the client internal store ID. |
empPosId | Number | POS numeric Employee ID |
regTtl | Number | Regular total pay amount |
extId | Number | Optional-Unique transaction ID for the time card record |
getTimeCardsV2
Same as getTimeCards but additionally provides double time info for each timecard.
getTimeCardsDeclaredTips
This method takes in a concept ID, store ID, start and end dates. It returns an array of wsTimeCard3 objects, which represent one employee time card each. Each time card has information for one employee punch record, including business date, regular and OT minutes and wages, clock in, clock out times and declared tips. If this store is using HotSchedules’ web-based timeclock for employee clock-in, any open punches in the date range are also included in the response.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getTimeCardsDeclaredTips?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016"
Sample JSON object
[
{
"breakMinutes": 0,
"empPosId": 4067,
"extId": -2031248,
"hsId": 929931332583,
"jobExtId": 18,
"jobId": -1,
"jobName": "Bartender",
"ovtHrs": 0,
"ovtMins": 0,
"ovtTtl": 0,
"ovtWage": 6.75,
"regHrs": 5.1,
"regTtl": 22.95,
"regWage": 4.5,
"spcHrs": 0,
"spcTtl": 0,
"storeNum": 2,
"businessDate": {
"day": 30,
"month": 4,
"year": 2016
},
"clockIn": "2016-04-30T09:29:00-05:00",
"clockOut": "2016-04-30T14:35:00-05:00",
"declaredTips": 0
}
]
Key | Type | Description |
---|---|---|
jobName | String | POS job code name |
ovtTtl | Number | Optional-Overtime total pay amount |
ovtHrs | Number | Optional-Overtime hours in shift |
clockOut | String | Clock out timestamp for the shift |
regWage | Number | Regular hourly pay rate |
clockIn | String | Clock in timestamp for the shift |
ovtWage | Number | Optional-Overtime hourly pay rate |
breakMinutes | Number | Number of non-paid break minutes in shift |
jobId | Number | POS numeric identifier for the job |
jobExtId | Number | POS numeric Job Code ID |
businessDate | Array | Business Date information, Day, Months and Year |
regHrs | Number | Regular hours represented in shift |
spcTtl | Number | Optional-Special Pay total pay amount |
hsId | Number | Optional-Internal HotSchedules employee Account ID. Not required, will be set by the service. |
spcHrs | Number | Optional-Special Pay Hours |
ovtMins | Number | Optional-Overtime minutes in shift |
storeNum | Number | Unique numeric store identifier. Generally set up to mirror the client internal store ID. |
empPosId | Number | POS numeric Employee ID |
regTtl | Number | Regular total pay amount |
extId | Number | Optional-Unique transaction ID for the time card record |
declaredTips | Number | Tip amount |
getVolumeCounts
This method will take a concept ID, store number, start and end dates and a volume type and return a list of volume counts for the date range requested. Supported Volume Types are: “TABLES”, “ENTRÉE”, “GUESTS”, “DELIVERIES”, “PRODUCTS”, and “TRANSACTIONS”.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
volumeType | volumeType | Classification of driver requested. Allowed types would be all of the classifications supported from API, HSC, or FTP integration. “Guests”, “Tables”, “Entrees”, “Deliveries”, “Transactions” and “Products”. |
start | hsSimpleDate | Start date for the range of data requested |
end | hsSimpleDate | End date for the range of data requested |
curl -X GET -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/getVolumeCounts?start_date=2015-04-30T00:00:00&end_date=2016-05-03T00:00:00&volume_type=TABLE"
Sample JSON response:
[
{
"dateTime": "2016-05-03T23:30:00-05:00",
"volumeAmount": 5,
"businessDate": "2016-05-03T00:00:00-05:00",
"volumeType": "Guests",
"rvcExtId": 0
}
]
Key | Type | Description |
---|---|---|
dateTime | String | Date of business |
volumeAmount | Number | Value of the volume count for the transaction |
businessDate | String | Business Date information, Day, Months and Year |
volumeType | String | Classification of driver requested. Allowed types would be all of the classifications supported from API, HSC, or FTP integration. “Guests”, “Tables”, “Entrees”, “Deliveries”, “Transactions” and “Products”. |
rvcExtId | Number | Represents the numeric revenue center ID associated with the volume count |
setTimeCardsV3
Extends dataTimeCard (includes business date and clock in and clockout date/times).
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start_day | Number | Day formatted dd |
start_month | Number | Month formatted mm |
start_year | Number | Year formated yyyy |
end_day | Number | Day formatted dd |
end_month | Number | Month formatted mm |
end_year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setTimeCardsV3?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016" -d "[{ \"jobName\": \"Cook\", \"ovtTtl\": 0, \"ovtHrs\": 0, \"clockOut\": \"2016-07-31T22:05:00-05:00\", \"regWage\": 9, \"clockIn\": \"2016-07-30T15:56:00-05:00\", \"ovtWage\": 13.5, \"breakMinutes\": 0, \"jobId\": 16921407, \"businessDate\": { \"month\": 7, \"year\": 2016, \"day\": 31 }, \"regHrs\": 6.15, \"spcTtl\": 0, \"hsId\": 929931334634, \"spcHrs\": 0, \"ovtMins\": 0, \"storeNum\": 1, \"empPosId\": 1052, \"regTtl\": 55.35 }]"
Sample JSON object
[
{
"jobName": "Cook",
"ovtTtl": 0,
"ovtHrs": 0,
"clockOut": "2016-07-31T22:05:00-05:00",
"regWage": 9,
"clockIn": "2016-07-30T15:56:00-05:00",
"ovtWage": 13.5,
"breakMinutes": 0,
"jobId": 16921407,
"businessDate": {
"month": 7,
"year": 2016,
"day": 31,
},
"regHrs": 6.15,
"spcTtl": 0,
"hsId": 929931334634,
"spcHrs": 0,
"ovtMins": 0,
"storeNum": 1,
"empPosId": 1052,
"regTtl": 55.35
}
]
Key | Type | Description |
---|---|---|
jobName | String | POS job code name |
ovtTtl | Number | Optional-Overtime total pay amount |
ovtHrs | Number | Optional-Overtime hours in shift |
clockOut | String | Clock out timestamp for the shift |
regWage | Number | Regular hourly pay rate |
clockIn | String | Clock in timestamp for the shift |
ovtWage | Number | Optional-Overtime hourly pay rate |
breakMinutes | Number | Number of non-paid break minutes in shift |
jobId | Number | POS numeric identifier for the job |
businessDate | Array | Business Date information, Day, Months and Year |
regHrs | Number | Regular hours represented in shift |
spcTtl | Number | Optional-Special Pay total pay amount |
hsId | Number | Optional-Internal HotSchedules employee Account ID. Not required, will be set by the service. |
spcHrs | Number | Optional-Special Pay Hours |
ovtMins | Number | Optional-Overtime minutes in shift |
storeNum | Number | Unique numeric store identifier. Generally set up to mirror the client internal store ID. |
empPosId | Number | POS numeric Employee ID |
regTtl | Number | Regular total pay amount |
extId | Number | Optional-Unique transaction ID for the time card record |
setEmpJobs
This method takes in a concept ID, store ID, and an array of WSEmpJob objects to assign jobs to individual employees. This method returns a WSReturn object.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setEmpJobs?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"hsJobId": 11878523,
"clientId": 14935376,
"regWage": 1,
"posEmpId": 2069,
"hsEmpId": 4177214,
"storeNum": 3,
"ovtWage": 1.5,
"posJobId": 18,
"primary": true
}
]
Key | Type | Description |
---|---|---|
hsJobId | Number | HotSchedules internal job code ID |
clientId | Number | Unique identifier for client provided via HotSchedules |
regWage | Number | Regular hourly wage rate for employee |
posEmpId | Number | POS numeric ID for employee |
hsEmpId | Number | HotSchedules internal employee account ID |
storeNum | Number | Unique numeric store ID within HotSchedules. Generally set up to mirror the client internal store IDs. |
ovtWage | Number | Overtime hourly wage rate for employee |
posJobId | Number | POS numeric ID for the job code |
primary | Boolean | Boolean flag to designate if the job code is the primary job for the employee |
setEmps
This method takes in a concept ID, store ID and an array of WSEmployee objects. Using the authentication from the username token and the conecpt and store IDs, the server will resolve which HotSchedules client this sync is for. The array of employees will be parsed on the server side to employees who need to be inserted or updated in the HS database. This method returns a WSReturn object.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
emps | wsEmployeeArray | Array of WSEmployee objects. Each object represents an employee at this store. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setEmps?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"zipCode": 78681,
"hireDate": "2017-08-03T10:16:38.533-05:00",
"termDate": "2017-11-05T10:16:38.533-05:00",
"address": "111 Addy Way",
"clientId": 25124840,
"LName": "Lockman",
"address2": "Unit 3",
"city": "Austin",
"mobile": "(222) 222-2222",
"NName": "Jay",
"altId": -1,
"FName": "Harrison",
"empNum": -1,
"phone": "(333) 333-3333",
"hsId": 587378309,
"dob": "1981-09-16T00:00:00-05:00",
"state": "TX",
"storeNum": 98,
"email": "harrison.lockman@email.com",
"status": 1
}
]
Key | Type | Description |
---|---|---|
zipCode | Number | Zip Code |
hireDate | String | Employee Hire Date |
termDate | String | Employee Termination Date |
address | String | Employee Address line 1 |
clientId | Number | Unique identifier for client provided via HotSchedules |
LName | String | Employee Last Name |
address2 | String | Employee Address line 2 |
city | String | City field for Address |
mobile | String | Employees Mobile Phone |
NName | String | Employee Nickname |
altId | Number | Employee HR ID. This must be a unique value across the company. It is used for HotSchedules Shared Employees. |
FName | String | Employee First Name |
empNum | Number | Employee POS ID |
phone | String | Phone Number |
hsId | Number | HS unique ID of an employee that is assigned at the time the employee is created in HS. This number is not configurable but automatically assigned. This number can be obtained through the get method and is an option to include in the set. However this is not necessary |
dob | String | Date of birth |
state | String | State |
storeNum | Number | Unique numeric store ID within HotSchedules. Generally set up to mirror the client internal store IDs. |
String | Employee’s email address | |
status | Number | Active = 1, Inactive = 0, Terminated = -1 |
setForecastDriversV2
This method takes in a startdate, enddate, starttime, endtime, volume amount, volume type, and a revenue center for the purpose of submitting forecasted volume drivers to HotSchedules from a third party system or point of sale. Using the authentication from the username token and the concept and store IDs, the server will resolve which HotSchedules client this sync is for. The array contains volume driver counts for a range of dates, corresponding to the start and end dates. The server side logic can handle overlapping data (i.e. if you sync 7 days worth of time cards, every day, 6 days of it will be “overlapping” data) and will insert and update data as needed. If the guest are already in the HS database and do not need to be updated, then nothing will change.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setForecastDriversV2?start_day=30&start_month=4&start_year=2016" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"driverAmount": 10,
"intervalStartDate" : {
"day": 15,
"month": 4,
"year": 2018
},
"intervalEndDate": {
"day": 15,
"month": 4,
"year": 2018
},
"intervalStartTime": {
"amPm": "pm",
"hours": 1,
"seconds": 0,
"militaryTime": false,
"minutes": 0
},
"intervalEndTime": {
"amPm": "pm",
"hours": 1,
"seconds": 0,
"militaryTime": false,
"minutes": 30
},
"rvcId": 1,
"volumeType": "Guests"
}
]
Key | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
workweekStartDate | Object | Start date of the work week |
driverAmount | Number | Quantity of driver for interval expressed in the record |
intervalStartTime | Object | The hour, minutes, and seconds corresponding to the start of the interval expressed in the record. Interval times are local to the store’s time zone. |
intervalEndTime | Object | The hour, minutes, and seconds corresponding to the end of the interval expressed in the record. Interval times are local to the store’s time zone. |
intervalStartDate | Object | The date corresponding to the start of the interval expressed in the record |
intervalEndDate | Object | The date corresponding to the end of the interval expressed in the record |
rvcId | Number | Numeric ID for the revenue center associated with the location within the restaurant |
volumeType | String | Classification of driver requested. Allowed types would be all of the classifications supported from API, HSC, or FTP integration. “Guests”, “Tables”, “Entrees”, “Deliveries”, “Transactions” and “Products”. |
setGuestCounts
This method takes in a concept ID, store ID, start and end date, business date, date time, guest count (must be a positive integer) and a revenue center for the purpose of submitting actual guest count drivers to HotSchedules from a third party system or point of sale. Using the authentication from the username token and the concept and store IDs, the server will resolve which HotSchedules client this sync is for. The array contains guest counts for a range of dates, corresponding to the start and end dates. The server-side logic can handle overlapping data (i.e. if you sync 7 days worth of time cards, every day, 6 days of it will be “overlapping” data) and will insert and update data as needed. If the guest are already in the HS database and do not need to be updated, then nothing will change. This method returns a WSReturn object.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
start_day | Number | Day formatted dd |
start_month | Number | Month formatted mm |
start_year | Number | Year formated yyyy |
end_day | Number | Day formatted dd |
end_month | Number | Month formatted mm |
end_year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setGuestCounts?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"dateTime": "2016-05-03T23:30:00-05:00",
"businessDate": "2016-05-03T00:00:00-05:00",
"guestCount": 113,
"rvcExtID": 123
}
]
Key | Type | Description |
---|---|---|
businessDate | String | Business date of transaction |
dateTime | String | Date Time of the transaction |
guestCount | Number | Number of guests for the transaction (must be a positive integer) |
rvcExtID | Number | Numeric ID for the revenue center associated with the transaction |
setRVC
This method takes in a concept ID and a store ID and returns an array of revenue centers for that store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept |
group | Number | Numeric ID group in which the store is assigned |
rvcId | Number | Numeric ID for the revenue center associated with the location within the restaurant |
rvcName | String | Name for the revenue center associated with the location within the restaurant. i.e. Bar, Togo etc… |
isGroupLevel | Boolean | Indicates if the revenue center is assigned at the group level. i.e. Bar used across all locations |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setRVC?group=1&rvcId=1&rvcName=1&isGroupLevel=true" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"concept": 1,
"group": 1,
"isGroupLevel": true,
"store": 13,
"rvcId": 11,
"rvcName": "Bar"
}
]
Key | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
group | Number | Numeric ID group in which the store is assigned |
rvcId | Number | Numeric ID for the revenue center associated with the location within the restaurant |
rvcName | String | Name for the revenue center associated with the location within the restaurant. i.e. Bar, Togo etc… |
isGroupLevel | Boolean | Indicates if the revenue center is assigned at the group level. i.e. Bar used across all locations |
setSalesCat
This method allows you to add the sales category associated with menu items. Sales categories will typically establish what kind of item was sold: Food, Beverage, Alcohol, Merchandise. Sales categories can be local to a particular store.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
group | Number | Numeric ID group in which the store is assigned |
salesCatId | Number | Numeric ID for the sales category associated with the location within the restaurant |
salesCatName | String | Name for the sales category associated with the item sold within the restaurant. i.e. Liquor, Beer, etc.. |
isGroupLevel | Boolean | Indicates if the sales category is assigned at the group level. i.e. Liquor ID 2 used across all locations |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setSalesCat?group=1&salesCatId=1&salesCatName=1&isGroupLevel=true" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"concept": 1,
"group": 1,
"isGroupLevel": true,
"store": 13,
"salesCatId": 9,
"salesCatName": "Liquor"
}
]
Key | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
group | Number | Numeric ID group in which the store is assigned |
salesCatId | Number | Numeric ID for the sales category associated with the location within the restaurant |
salesCatName | String | Name for the sales category associated with the item sold within the restaurant. i.e. Liquor, Beer, etc.. |
isGroupLevel | Boolean | Indicates if the sales category is assigned at the group level. i.e. Liquor ID 2 used across all locations |
setSalesItemsV4
This method takes in a concept ID, store ID, a start and end date and an array of WSSalesItem objects. Using the authentication from the username token and the concept and store IDs, the server will resolve which HotSchedules client this sync is for. The array contains sales items for a range of dates, corresponding to the start and end dates. The server-side logic can handle overlapping data (i.e. if you sync 7 days worth of sales, every day, 6 days of it will be “overlapping” data) and will insert and update data as needed. If the sales items are already in the HS database and do not need to be updated, then nothing will change. The method returns a WSReturn object. This method uses hsSimpleDate objects for dates.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setSalesItemsV4?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
"concept": 1,
"storeNum": 1,
"sales": {
"catName": "Beer",
"clientId": 3,
"empId": 123,
"extId": 333,
"rvc": "Revenue",
"rvcName": "Bar",
"salesCat": "Beer",
"storeNum": 3,
"ttl": 0,
"businessDate": {
"day": 1,
"month": 7,
"year": 2016
},
"transDate": {
"day": 1,
"month": 7,
"year": 2015
},
"transTime": {
"amPm": "am",
"hours": 1,
"militaryTime": true,
"minutes": 15,
"seconds": 0
}
},
"start": {
"day": 1,
"month": 7,
"year": 2016
},
"end": {
"day": 1,
"month": 8,
"year": 2016
}
]
Key | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept |
catName | String | Category name |
clientId | Number | Unique identifier for client provided via HotSchedules |
empId | Number | Employee ID |
extId | Number | External ID |
rvc | String | Revenue Center |
rvcName | String | Name for the revenue center associated with the location within the restaurant |
salesCat | String | Sales category |
ttl | String | Total sales for the sales category |
businessDate | Object | Business Date information, Day, Months and Year |
transDate | Object | Transaction date |
transTime | Object | Transaction time |
start | Object | Start date for the range of data requested |
end | Object | End date for the range of data requested |
setTimeCardsDeclaredTips
This method takes in a concept ID, store ID, a start and end date and an array of WSTimeCardsDeclaredTips objects. Using the authentication from the username token and the concept and store IDs, the server will resolve which HotSchedules client this sync is for. The array contains time cards for a range of dates, corresponding to the start and end dates. The server-side logic can handle overlapping data (i.e. if you sync 7 days worth of time cards, every day, 6 days of it will be “overlapping” data) and will insert and update data as needed. If the time cards are already in the HS database and do not need to be updated, then nothing will change. This method returns a WSReturn object.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
Day | Number | Day formatted dd |
Month | Number | Month formatted mm |
Year | Number | Year formated yyyy |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setTimeCardsDeclaredTips?start_day=30&start_month=4&start_year=2016&end_day=5&end_month=5&end_year=2016" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"breakMinutes": 0,
"empPosId": 4067,
"extId": -2031248,
"hsId": 929931332583,
"jobExtId": 18,
"jobId": -1,
"jobName": "Bartender",
"ovtHrs": 0,
"ovtMins": 0,
"ovtTtl": 0,
"ovtWage": 6.75,
"regHrs": 5.1,
"regTtl": 22.95,
"regWage": 4.5,
"spcHrs": 0,
"spcTtl": 0,
"storeNum": 2,
"businessDate": {
"day": 30,
"month": 4,
"year": 2016
},
"clockIn": "2016-04-30T09:29:00-05:00",
"clockOut": "2016-04-30T14:35:00-05:00",
"declaredTips": 0
}
]
Key | Type | Description |
---|---|---|
jobName | String | POS job code name |
ovtTtl | Number | Optional-Overtime total pay amount |
ovtHrs | Number | Optional-Overtime hours in shift |
clockOut | String | Clock out timestamp for the shift |
regWage | Number | Regular hourly pay rate |
clockIn | String | Clock in timestamp for the shift |
ovtWage | Number | Optional-Overtime hourly pay rate |
breakMinutes | Number | Number of non-paid break minutes in shift |
jobId | Number | POS numeric identifier for the job |
jobExtId | Number | POS numeric Job Code ID |
businessDate | Array | Business Date information, Day, Months and Year |
regHrs | Number | Regular hours represented in shift |
spcTtl | Number | Optional-Special Pay total pay amount |
hsId | Number | Optional-Internal HotSchedules employee Account ID. Not required, will be set by the service. |
spcHrs | Number | Optional-Special Pay Hours |
ovtMins | Number | Optional-Overtime minutes in shift |
storeNum | Number | Unique numeric store identifier. Generally set up to mirror the client internal store ID. |
empPosId | Number | POS numeric Employee ID |
regTtl | Number | Regular total pay amount |
extId | Number | Optional-Unique transaction ID for the time card record |
declaredTips | Number | Tip amount |
setVolumeCountsV2
This method takes in a concept ID, store ID, business date, date time, volume amount, volume type, and a revenue center for the purpose of submitting actual volume drivers to HotSchedules from a third party system or point of sale. Using the authentication from the username token and the concept and store IDs, the server will resolve which HotSchedules client this sync is for. The array contains volume driver counts for a range of dates, corresponding to the start and end dates. The server-side logic can handle overlapping data (i.e. if you sync 7 days worth of time cards, every day, 6 days of it will be “overlapping” data) and will insert and update data as needed. If the guest are already in the HS database and do not need to be updated, then nothing will change. This method returns a WSReturn object.
Query parameter | Type | Description |
---|---|---|
concept | Number | The identifier for the location’s concept. Must be unique within the company, contact HotSchedules if you’re not sure about this value. |
storeNum | Number | Numeric (integer) identifier for the store. Must be unique within the concept. |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setVolumeCountsV2" -d "[{json_object_1}, {json_object_2}, {json_object_3}...]"
Sample JSON object
[
{
"businessDate": "2014-10-05T00:00:00",
"dateTime": "2014-10-05T06:41:00-05:00",
"rvcExtId": 4,
"volumeAmount": 1,
"volumeType": "GUESTS"
}
]
Key | Type | Description |
---|---|---|
businessDate | String | Business date of transaction |
dateTime | String | Date time of transaction |
rvcExtId | Number | Represents the numeric revenue center ID associated with the guest |
volumeAmount | Number | Value of the volume count for the transaction |
volumeType | String | Classification of driver requested. Allowed types would be all of the classifications supported from API, HSC, or FTP integration. “Guests”, “Tables”, “Entrees”, “Deliveries”, “Transactions” and “Products”. |
setLaborForecastByJob
This method takes in a concept ID, store ID, business date, daypart start and end times,labor forecast and jobExtId. Forecasted labor for the site, date, internal and job will be updated for the purpose of labor scheduling and all relevant reports. The call can be sent for a full week or single date. All intervals must be updated. A zero in the interval is an acceptable value. A null or blank is an acceptable value and will be treated as a zero. If sent for a single date only the date provided will be updated. All other dates within the week will not be impacted and any values already in the database will be retained. A full day’s data must be sent, updating only one interval within a business date is not permitted and the call will fail.
Query Paramater | Type | Description |
---|---|---|
concept | int | The identifier for the location’s concept/group. Must be unique within the company. Contact HotSchedules if you’re not sure about this value. | storeNum | int | Numeric (integer) identifier for the location. Must be unique within the concept. | jobs | wsEmpJobArray | Array of WSEmpJob objects. Each object represents one employee job, so a single employee can have one or more employee jobs (EmpJob) assigned to him/her. Each job that the employee works will be a separate object in this array. | day | int | Formatted dd | month | int | Formatted mm | year | int | Formatted yyyy | dayPartStartTime | dateTime | Day part start time | laborForecastMinutes | int | Minutes value | jobExtRef | int | Job reference id |
curl -X PUT -H "Content-Type:application/json" -u <username>:<password> "https://api.hotschedules.io/<namespace>/controllers/vertx/hotschedules/<concept>/<storeNum>/setLaborForecastByJob"
Sample JSON object
[
{
"businessDate":{
"day":3,
"month":9,
"year":2018
},
"dayPartStartDate":{
"day":3,
"month":9,
"year":2018
},
"dayPartStartTime":1145,
"laborForecastMinutes":15,
"jobExtRef":11
}
]
Agent Integration
Overview
The Agent provides a single integration point that enables in-store and near-store data collection.
The Platform provides real time bi-directional connections between the cloud and POS via existing Macromatix Livelink and HotSchedules Connect integrations, as well as an an in-store appliance and software agent.
The IoT Platform is built on open standards and integrates with:
- In-store data sources, such as POS systems, equipment, scheduling systems (e.g. HotSchedules) and sensors (e.g., thermometers, energy meters, batteries, HVAC)
- Near-store apps (e.g. Yelp, weather data, traffic data, Facebook)
- Above-store apps such as inventory management, ordering systems (e.g.Macromatix), accounting) and other internet connected services
Getting Started
The HotSchedules IoT Platform Agent provides a single integration point that enables in-store and near-store data collection. The Agent allows you to integrate with in store data, above store data and near store data.
Environment Setup
Installation
The agent cli is installed via a platform specific installer or via node package manager (NPM). The cli prefers to be installed globally.
$> npm install -g agent-cli
General Usage
The general structure of the a command is as follows:
$> npm install agent-cli [options] <action> [arguments]
Options
Options are prefixed with -
or --
to separate them from arguments. Each action defines the options it uses, but the options are consistent in naming and usage across the commands.
Common Options
long | short | arg | description |
---|---|---|---|
–help | none | none | print help about the command |
–verbose | -v | none | print more detailed output |
–quiet | -q | none | print essential output |
–config | -f | path | specifies the agent’s configuration file |
–home | -h | path | specifies the agent’s working directory |
–force | -F | none | directive to override safety logic |
Arguments
The cli interprets the first argument (non-option) as the action. All subseuqent arguements are command specific.
Each action is described below:
Informational Commands
help
The command line provides built in helper functions.
Navigation Help
For a descriptive list of the commands
$> npm install agent-cli --help
Action Specific Help
Action specific help can be requested using the following structure.
$> npm install agent-cli <action> --help
version
Print version information.
$> agent-cli --version
$> agent-cli -V
The output is a simple version identifier following the semantic versioning rules of major, minor, and build.
vM.m.b
info
CLI splash screen for the agent.
$> agent-cli info
Lifecycle Commands
Lifecycle commands allow an administrator to change and check the run state of an agent.
start
Attempts to start an agent.
$> agent-cli start [options]
Options
long | short | arg | deacription |
---|---|---|---|
–verbose | -v | none | print more detailed output |
–quiet | -q | none | print essential output |
–config | -f | path | specifies the agent’s configuration file |
–home | -h | path | specifies the agent’s working directory |
status
Provides status about a running agent.
$> agent-cli status [options]
Options
long | short | arg | deacription |
---|---|---|---|
–verbose | -v | none | print more detailed output |
–quiet | -q | none | print essential output |
–config | -f | path | specifies the agent’s configuration file |
stop
Gracefully shutdown the agent.
$> agent-cli stop [options]
Options
long | short | arg | deacription |
---|---|---|---|
–verbose | -v | none | print more detailed output |
–quiet | -q | none | print essential output |
–config | -f | path | specifies the agent’s configuration file |
Diagnostic Commands
Diagnostic commands are used by an admin to troubleshoot an agent having trouble entering a running state or to test environmental specific details uniformly across platforms.
check-core
Used to check the version of agent-core being used and where that file is located on the file system.
$> agent-cli check-core [options]
Options
long | short | arg | deacription |
---|---|---|---|
–config | -f | path | specifies the agent’s configuration file |
check-config
Used to check for configuration problems in the agent. The agent will load and process all configuration files, but will not enter into a ready state. This command is safe to run even if there is a currently running agent.
$> agent-cli check-cofig [options]
Options
long | short | arg | deacription |
---|---|---|---|
–config | -f | path | specifies the agent’s configuration file |
check-connection
Used to check for configuration problems in the agent.
$> agent-cli check-connection [options]
Options
long | short | arg | deacription |
---|---|---|---|
–config | -f | path | specifies the agent’s configuration file |
The provided URL will go through the following checks:
- Check the URL format
- Check the DNS resolution from the agent’s host
- Check the TCP port is reachable by opening up a connection on host:port
- Issue a HTTP GET against the ping endpoint of the system
check-route
Used to check for network problems (firewalls & proxy rules) from the perspective of the agent runtime.
$> agent-cli check-route <scheme://host:port/path>
The provided URL will go through the following checks:
- Parse
- DNS resolve of host/IP
- TCP port reachable by opening up a connection on host:port
- If scheme is http of https then issue a HTTP GET against the specified URL
Installing Bodhi Agent
Agent Installer and Registration User Guide
Welcome to the User Guide for Installing and registering the Bodhi agent
System Requirements for computer
OS: Windows XP SP3, Windows 7, Windows 8.1
Memory: 2GB or more
Disk Space: 10 GB
System requirements for Mobile
iOS 7.x, 8.x
Android 4.x
Windows Phone
Step 1: Download Bodhi Installer and the Bodhi Mobile Application
Go developer.hotschedules.io to get the correct installer for your system
NOTE: if the system you are using to download the installer is not a Windows system you will get the Not Supported.
Just select the Windows system that matches the system you will be installer the Bodhi Agent on.
For the mobile applications here is where you can download them to your device.
Bodhi Mobile - iOS Apple Apps Store
Bodhi Mobile - Android Google Play Store
Step 2: Run the installer
- You will be presented with the Installer Welcome screen.
- This will show the version number of the installer
Step 3: Select the Next button to move to the next Button
Step 4: License agreement screen
- The user needs to agree to the user agreement before proceeding.
NOTE: the Next Button will be greyed out, until the, I accept the agreement radio button is selected.
Step 5: Select the I accept the agreement Radio Button
Step 6: Select the Next Button
Step 7: Selecting the Destination location for the Agent
- A default destination location is already provided for the agent.
NOTE: If this destination location is OK, then select the Next Button.
Go to Step 8
Step 7a: If you wish to change the location of the destination location
7a. Select the Browse Button
7b. Select the folder you wish to install the Bodhi Agent into or you can open a different folder.
7c. After you have selected the folder
7d. Select the OK Button
The New destination location should be displayed
7e. Select the Next Button to continue
Step 8: Review of Destination location.
- The destination location for the install is displayed.
Step 9: Select the Install Button
- If the Destination location is correct, then
- Select the Install Button
9a. A Progress bar will be displayed
Step 10: Installing Nodejs page
- After the Setup Wizard has completed installing the agent and it parts, the installer for NodeJS is started.
Step 11: Selecting the Next Button
- Select the Next button to continue the install of Nodejs.
Step 12: License agreement screen
- The user needs to agree to the user agreement before proceeding
NOTE: the Next Button will be greyed out, until the, I accept the agreement checkbox is selected.
Step 13: Select the I accept the agreement Radio Button
Step 14: Select the Next Button
Step 15: Selecting the Destination location for Nodejs
- A default destination location is already provided for Nodejs.
NOTE: If this destination location is OK, then select the Next Button.
Go to Step 16
Step 15a: If you wish to change the location of the destination location, Select the change Button
Step 15b. Select the folder you wish to install nodejs into or you can open a different folder
Step 15c. After you have selected the new folder
Step 15d. After you have selected the folder in the new selected folder
Step 15e. Select the OK Button
Step 15f. Review the Destination location
Step 16: Review of the Custom Setup.
- The Custom Setup page for the install is displayed.
Step 17: Select the Install Button
- If all the information is correct, then
- Select the Install Button
15h. A Progress bar will be displayed
Step 16: Completing the HotSchedules Link Setup Wizard page
- After the Setup Wizard has completed, a checkbox is presented, by default it is selected.
10a. Completing the HotSchedules Link install
- If no change is required, then Select the Finish Button
figure 19
10b. Command Line Interface is opened
- A Diagnostics is run
- The Windows Service is started
- Follow the instructions to press any key to continue
figure 20
10c. The command line window should close and you will be at the Desktop.
figure 21
Step 1: Register the Agent with a Mobile Device
- If you had selected to start the console at the end of the install, then the console will be started in the default browser.
Note: If your agent is not registered, it will be unable to send any data to the cloud
- A Registration Code will be displayed which is used to register the POS with the Mobile Device.
figure 22
Note: If the registration dialog is dismissed before registration * Select the Registration Code Menu item on the left to redisplay it
figure 23
Step 2: Start the Bodhi Mobile App
- This is the Mobile Application that was downloaded earlier to your Mobile Device
figure 24
Step 3: Enter the a Mobile Device
- Enter the UserID
- Enter the Password
- Select the Log in Button
figure 25
Step 4: Select the POS Manager
figure 26
Step 5: Select the the Plus Sign to add a POS to the Manager
figure 27
Step 6: Select a store to associate the POS with.
figure 28
Step 7: Enter the Activation code that is displayed in the Browser.
figure 29
Step 8: Select the Request Button.
figure 30
Step 9: Verify that POS agent with the selected store and is displayed
figure 31
Step 20: The Browser will display the console dashboard
- A Success message will briefly flash on the screen
- The Registration Code Menu item will be removed
- The Dashboard will be displayed
figure 32
Console Dashboard Legend
- This is the status of the agent (e.g. Online, Offline)
- This changes the Left Menu from Icon Only to Icons and Text
Congratulations on your successful installation of Bodhi Agent
Creating an Agent Application
Configuring Agent Application
Parameters
Mutable environmental variables that can be modified in Agent Manager. Values can overwrite default settings.
Property | Type | Description |
---|---|---|
description | String | Description in Agent manager application |
type | String | Expected data type of parameter value |
setting | String | Assigned variable name to this parameter |
required | Boolean | True or False |
default | String | The default value of the parameter if not set |
Parameters example
parameters : {
master_id: {
description : 'System ID of Master Agent',
setting : 'master_id',
type : 'string',
required : true
},
role: {
description : 'Role of Master Agent for Slave to assume',
type : 'string',
setting : 'role',
required : true
}
}
Extensions
Extensions are injected dependencies that your application can refer to. Your application may use one or more extensions. Extensions can provide potential configuration components or actual runtime components. Extensions are a good way to design resuable components that can be shared and reused across projects. Extensions are loaded in the order in which they are specified.
Property | Type | Required | Description |
---|---|---|---|
module | String | Yes | By default searches node_modules folder. Relative path also accepted. |
Extensions example
extensions : [
{ module: './lib/plugin.js' },
{ module: 'agent-ext-timers' }
]
Settings
A Setting is an Object that represents static configuration data. Parameters can overwrite a setting if the property matches a parameter key. These values will take the highest precedence in the processing of settings. The precedence rules are:
- Agent.json settings object (highest precedence)
- Any settings within the js/json files in the settings folder
- Any settings added by an extension (lowest precedence)
Property | Type | Required | Description |
---|---|---|---|
property | String | Yes | Name of your property |
value | String, Function, Boolean, Number, Object | Yes | The value of your setting |
Settings example
settings: [
{
property: 'master_id',
value: '588f9fc508a94349cc1ad3b8'
},
{
property: 'role',
value : 'pos-monitor'
}
]
Counters
Tracks the number of times specific application events occur and are logged found in the Agent heartbeat. Each counter can subscribe to an array of application events.
Counters example
counters: {
activations : ['app:monitor'],
success : ['app:success'],
stopped : ['app:stopped'],
failed : ['app:failed' ]
}
Sources
An object that sources external events. Sources bind events to listeners and emits application level events. Any counters, handlers and pipelines subscribed to source events are initiated.
Property | Type | Required | Description |
---|---|---|---|
name | String | Yes | Unique identifier (within the context’s handler) |
provider | String or Function | Yes | A function or reference to a plugin that creates an object |
args | Array of Strings, Functions, Objects, Booleans | Optional | A list of dependencies used by the source |
bindings | Object | Optional | A Map that routes external events to internal topics |
factory | String | Optional | An enumeration that describes alternate instantiation behavior for the service constructor, function, literal |
Sources example
sources: [
{
name: 'sampleSource',
provider: 'compris:dir',
args: ['$settings:rootPath'],
bindings: { 'created' : 'read' }
}
]
Services
A Service is an Object that represents a concrete extension of the API. Services are singletons.
Property | Type | Required | Description |
---|---|---|---|
name | String | Yes | Unique identifier (within the context’s handler) |
provider | String or Function | Yes | A function or reference to a plugin that creates an object |
args | Array of Strings, Functions, Objects, Booleans | Optional | A list of the dependencies used by the service |
factory | String (Constructor, Function, Literal) | Optional | An enumeration that describes alternate instantiation behavior for the service |
Services example
services: [
{
name: 'cloud',
provider: 'connection:resources'
}
]
Handlers
A Handler is a Function that responds to events within an application.
Property | Type | Required | Description |
---|---|---|---|
name | String | Yes | Unique identifier (within the context’s handler) |
subscriptions | Array |
Yes | String of application level events that will initiate this handler |
fn | String or Function | Yes | A function or reference to a plugin will handle the events |
props | Object | Optional | A list of properties available to the instance |
Handlers example
handlers: [
{
name : 'Monitor Master Agent',
subscriptions : ['app:monitor'],
fn : '$plugins:handler:monitor',
props : {
master_role : '$setting:role',
conn : '$service:cloud',
master_id : '$setting:master_id',
getInfo : '$plugins:core:info',
identity : '$plugins:core:identity',
}
},
{
name : 'Update Agent Role',
subscriptions : ['app:update'],
fn : '$plugins:handler:update',
props : {
conn : '$service:cloud',
}
}
]
Pipelines
Similar to handlers, pipeline(s) are subscribed to event(s). The difference being that pipelines execute a series of steps rather than just one function. Each pipeline step should follow the single responsiblity principle. Each step is given two arguments - input and a callback.
Property | Type | Required | Description |
---|---|---|---|
name | String | Yes | Unique identifier |
subscriptions | Array | Yes | String of application level events that will initiate this pipeline |
steps | Array | Yes | Takes an array of objects described below |
failed | String | Optional | Emits mapped event based on the state of the pipeline |
success | String | Optional | Emits mapped event based on the state of the pipeline |
done | String | Optional | Emits mapped event based on the state of the pipeline |
Pipeline.steps
pipeline | Object
Property | Description |
---|---|
fn | Functional plugin reference. See pipeline and fn description below |
props | Optional dependencies to be injected in the pipeline function context |
Pipeline.fn(input, callback)
input | Object
Initially an empty object. Later becomes whatever the result of the previous pipeline step is.
callback | Function
Needs to be invoked with a possible error arguement and an optional result to be passed in to the next step.
If an error is passed in, it will stop the pipeline and the failed event will be emitted.
Context of this callback includes core methods described below as well as Pipeline.props injected during configuration.
Property | Description |
---|---|
logger | Logs viewable in Agent Manager |
publish | EventEmitter that takes in a event and message |
name | Pipeline.name |
event | Name of event that triggered the pipeline |
Pipelines example
// pipeline breakdown of handlers
pipelines: [
{
name: 'Monitor Master Agent',
subscriptions: ['app:monitor'],
steps: [
{ fn: '$plugins:core:identity:addAgentInfo' },
{ fn: '$plugins:main:checkMasterAgentStatus' },
{ fn: '$plugins:main:processAgentStatus' }
],
stopped : 'app:stopped',
failed : 'app:failed'
},
{
name: 'Update Status',
subscriptions: ['app:update'],
steps: [
{ fn: '$plugins:main:patchAgentRole' },
{ fn: '$plugins:main:syncAgent' }
],
stopped : 'app:stopped',
failed : 'app:failed'
}
]
Init
Init is a function that is given a callback as its only argument. This callback must be invoked in order to intialize the application. The keyword “this” refers to the application’s reactive context
Init example
init: function(done){
this.publish('app:initialized');
console.log('###################################');
console.log('## ' + pkg.name.toUpperCase());
console.log('## v' + pkg.version);
console.log('###################################');
done();
}
Creating an Agent Source
Returns a function that instantiates an Agent source. See sample code that watches for any directory changes using npm watch.
Sample Code:
var fs = require('fs-extra');
var watch = require('watch');
module.exports = function dirSrc() {
var path = arguments[0];
var source = {};
source.routers = {};
var bind = function bindDir(bindings, emitter, done) {
var logger = this.logger;
logger.info('Ensuring ', path, 'exists...');
if (!path) return done('Expected path to exist. Please ensure args array is properly configured.');
fs.ensureDir(path, function (err) {
if (err) return done(err);
logger.info(path, 'ensured.');
/*
bindings = { 'created' : 'read' }
emitter = fn() { context.emit.apply(context, arguments); }
done = fn() { return exit(done, source); }
YOU HAVE TO CALL DONE OR ELSE THE REST OF THE APP WILL NOT LOAD
KICK LISTEN OR IT WILL NOT HEAR
*/
// routes = ['created']
var routes = Object.keys(bindings);
/*
routers = {
emitter(event, arguments);
}
}
*/
routes.forEach(function (event) {
source.routers[event] = function () {
emitter(bindings[event], { path: arguments[0], detail: arguments[1] });
}
});
done();
});
};
/*
SOURCES GET LOADED BEFORE INIT
ENSURE DIR BEFORE SETTING MONITORS
*/
var listen = function listenDir(cb) {
watch.createMonitor(path, function (monitor) {
source.monitor = monitor;
['created', 'changed', 'removed'].forEach(function (e) {
if (source.routers[e]) {
source.monitor.on(e, function (file, detail) {
source.routers[e](file, detail);
});
}
});
});
};
var close = function closeDir() {
source.monitor.stop();
};
return function (cb) {
cb(null, { bind: bind, listen: listen, close: close})
}
};
Property | Type | Description |
---|---|---|
bind | Function | Responsible for binding application level events when a source level event occurs |
listen | Function | Creates EventEmitter that emit application level events based on bind |
close | Function | Destroy existing EventEmitter for the source |
Creating an Agent Extension
Returns an Agent extension object.
Property | Type | Description |
---|---|---|
name | String | Name of extension used primarily for debugging purposes |
attach | Function | Attach the specified extension to this instance, extending the ReactiveContext with new functionality with the implicit registerPlugin method |
Sample Code:
module.exports = {
name : 'plugin',
attach : function (overloads, done) {
/** LOAD HANDLERS **/
this.registerPlugin(['handler', 'monitor' ], require('./handlers/monitor.js' ));
this.registerPlugin(['handler', 'update' ], require('./handlers/update.js' ));
done();
}
};
Agent Path Resolution
Every extension, service and setting can be injected through namespacing
Type | Reference | Sample |
---|---|---|
extension | “$plugins” | “$plugins:myFunction” |
service | “$service” | “$service:cloud” |
setting | “$setting” | “$setting:jobInterval” |
Job Engine
Creating a job engine application
Introduction
Bodhi Job Engine is a job scheduler running on node.js and MongoDB. The engine is designed to run scheduled cloud-to-cloud data transactions, e.g. requesting data from web APIs, pushing data to the Bodhi cloud, etc.
Work Functions
Jobs must be built in a specific format in order for Bodhi Job Engine to recognize and run them properly. The job should contain an index.js file that follows this structure:
index.js
module.exports = function work(context, done){
//the work of your job
done(errThatOccurred, messageToReport, stateToSave);
};
Context Object
Key | Type | Description |
---|---|---|
connection | bodhi-js-client | https://www.npmjs.com/package/bodhi-driver-superagent |
settings | Object | immutable configuration options associated with this job |
state | Object | mutable persistent state from previous runs |
meta | Object | immutable metadata about the job |
meta
{
}
Job Metadata
Key | Type | Description |
---|---|---|
name | String | name of the job |
package | String | package name |
version | String | semantic package version |
namespace | String | namespace of the job |
lastRun | Data | last time the job ran |
Callback
A job must be completed by calling the callback
arg | type | required | description |
---|---|---|---|
err | Error | optional | if err != null then the job did not process properly |
message | String | optional | a string to be recorded in the message |
state | Object | optional | the state to persist for the next run |
Example Job: Hello World
This is a very basic Hello World job.
module.exports = function(options, done){
console.log('HELLO WORLD!');
if(err){
done(err);
}
else{
done();
}
};
Example Job: Get and Use Some Data
Get and use data
module.exports = function(options, done){
var client = options.connection;
var data = options.state;
data.storestuff = [];
client.get(['resources', 'Store'].join('/'), function(err, data, ctx){
if(err){
done(err);
}
else{
data.forEach(function(store){
data.storestuff.push(store.store_name + ' is an awesome store!');
});
}
});
var json = {
"data1": "some data you need to post",
"data2": "also data you need to post"
};
client.post(['resources', 'aCustomType'].join('/'), json, function(err, data, ctx){
if(err){
done(err);
}
else{
console.log('Server says: ', ctx);
done();
}
});
};
This is a less basic example job that uses HTTP requests and stores data in the “state” property of the options object. Data stored in the state property persists between jobs and is available in the next execution of the job.
Publishing Applications
Overview
To publish application for the IoT Platform, you need to follow a few simple steps to describe your application.
Configuring package.json
To publish your application, add the following directory structure for your application:
/<app-name>/
/public/
- Folder (npm app-name)
- index.js
- LICENSE (standard apache license file)
- package.json (example provided below)
- public (folder)
- app_icon.png
- NewType1.json file (optional)
- NewType2.json file (optional)
- NewType3.json file (optional)
To publish an app into the IoT Platform you have to zip up the following:
index.js
LICENSE
package.json
folder=<public>
app_icon.png
NewType1.json file (optional)
NewType2.json file (optional)
NewType3.json file (optional)
...
Example package.json for Mobile Applications
By Clicking on HS Template you get a package.zip file that is downloaded to your desktop that contains the following:
index.html
If you open this file it say Click Me and a Welcome will appear above Click Me
LICENSE This is the apache2 license file that needs to be with all applications you plan to build
README.md
README.md are directions to get started developing your mobile application
image_home.png Image_home.png is the background image for index.html
package.json:
This is the example package.json that you will cutomize based on your application needs. To the right is a formatted version of the sample package.json that is included in HS Template’s zip file.
package.json that gets includes with HS Template's zip file:
{
"name": "HSappTemplate",
"version": "0.0.0",
"title": "HSappTemplate",
"description": "New application Hello, World!",
"profile": {
"name": "HSappTemplate",
"dml": {
"BodhiApplication": {
"select": {}
}
}
},
"settings": {
"publisher": "",
"categories": [""],
"offline": false,
"navigationBar": "auto",
"location": "S3",
"storage": "s3",
"type":"mobile"
},
"dependencies": {
"bodhi-mobile":"*"
},
"autoUpdateVersion": true
}
Example of Package.json for agent or job Applications
Example of package.json for agent or job applications:
#!javascript
{
"name": "app-package-name",
"version": "0.0.1",
"title": "Application Title",
"description": "Short Application Description.",
"profile": {
"name": "app-package-name",
"dml": {
“BodhiApplication": {
"select": {},
"update":{},
"delete":{},
"insert":{}
},
"NewType1": {
"select": {}
},
"NewType2": {
"select": {}
}
}
},
"settings": {
"categories": [
"Aloha",
"POS"
],
"publisher": "your company",
"npm_package_name": "app-package-name",
if you have any related apps you want to install together::
"related-apps": [
"bodhi.aloha-app-transactions",
"bodhi.aloha-app-store"
],
"public_path": "public",
"global_store_icon": "public/icon.png",
"location": "S3",
"storage": "s3",
"type": "agent",
(type can be “job”, “agent”, “mobile”, “web” )
"new_type_required": true,
"install": {
"new": {
"model": [
{
"type": "enumeration",
"name": "TypeName",
"object": "Enumerations/TypeName.json"
},
{
"type": "embedded_type",
"name": "InventoryPurchaseOrder",
"object": "Types/InventoryPurchaseOrder.json"
},
{ "type": "custom_type",
"name": "TypeName2",
"object": "Types/TypeName2.json"
}
],
"post-type-install": [
{"action": "POST",
"object": "Data/DataFile.json",
"path": "/resources/DataFile"
}
]
if you have any parameters required to be used with the app we add this section::
"agent_parameters": {
"interval": {
"description": "How often to execute a grind",
"required": true,
"type": "string",
"default": "every 15 minutes",
"position": 1
}
}
},
"autoUpdateVersion": false
}
Description of package.json contents
name=“HSappTemplate” required
The name of your application must match the name of the profile
“version”: “0.0.1” required
Ideally this is the version of your application that gets posted as versions show for Agent Application in the Agent Event Logs so keeping this version the same as your Agent Application that is published is highly recommended.
“title”: “Application Title” required
This is the title that will show on the HotSchedules Store once you publish your application to the HotSchedules Store.
“description”: “Short Application Description.” required
The description is the application description that will be displayed with the title for your application when displayed in the HotSchedules Store. Description will be part of “Learn More” button.
“profile”: {} required
The profile section contains the following required sections:
“name”: “HSappTemplate” required and must match name above
The profile name must match the application name that is described in the main part of the package.json (see name=“app-package-name” required above)
“dml”: {}
DML=Data Manipulation Language and this section describes what operations you plan to use on the schema or types within your application. Usually you define the type and what operations you want to allow on the type such as select, update, delete, insert and/or aggregate. How you describe your DML section depends on what types you access and how you access/manipulate them.
“settings”:{} required
The settings is the main section of package.json contains the following sections:
“categories”: [] optional
A list of comma separated categories your application would fit into. The categories array allows you to give the HotSchedules Store taxonomical information about how your app relates to other applications. Examples include financial, inventory, management
“publisher”: “your company” required
This is the name of your company or your name if you are self-represented.
“npm_package_name”: “app-package-name” required if building an Agent App or Job App
“related-apps”: [] optional Define the array of related applications as a comma separated based on the application(s)’ global package name. Example: “related-apps”: [ “bodhi.aloha-app-transactions”, “bodhi.aloha-app-store” ]
“offline”: false Required for mobile application
Offline is for mobile applications and tells the mobile container (HotSchedules Passbook). Offline controls whether the container will cache application information for offline use. If offline=true and the user launches the application, any data that was previously loaded will be available when the device is offline. This will also enable queuing of data to write to the Bodhi Cloud if the app has write permissions.
“navigationBar”: “auto”
NavigationBar is for mobile applications and tells the mobile container (HotSchedules Passbook) to automatically use the built in navigation bar.
“public_path”: “public” required
Public path is the folder that hold any screenshots, icons, and/or type definitions. The Public Path is a location off of root of your application that allows developers to save items that should be publicly visible and available. The Public Path folder should contain screenshots and Icons that the global app store can use. The global_store_icon as well as the screenshots settings objects should all be relative paths to the public path.
“global_store_icon”: “public/icon.png” required
In the settings section, Global Store Icon is your icon for your application.
“location”: “S3” optional
In the settings section, you define where your published app resides (S3 or artifactory). S3 is the preferred location. The Agent Apps used to use “storage”: “s3”, so that needs to be included in the settings sections as well for agent apps to compatibility.
“type”: “mobile” required
In the settings section, you define the type of application (job, agent, mobile or web) you are publishing. The “type”=“job” define your application to run inside job engine through Job Engine Manager. The “type”=“agent” defines your application to run with the agent based on a defined role. The “type”=“mobile” defines your application to run in a mobile container usually HotSchedules Passbook. The “type”=“web” defines your application to run as a web application.
“new_type_required”: true optional
In the settings section, if you are adding new types as described below, then this flag should be set to true. new_type_required tells the installer of the app in the global app store if the app will run ‘out of the box’ or if new custom types need to be installed on the namespace. NOTE:: if new_type_required=true, troubleshootingurl should be required_
troubleshooting_url='http://tools.hotschedules.io/xxxx’ NOTE:: if new_type_required=true, troubleshootingurl should be required_
The troubleshooting_url is the URL where the customer can find additional information about how to install custom types on their namespace to get an app to function correctly. This can also be used to FAQ’s or any other outbound troubleshooting you would like to provide to your customers.
agent_parameters/job_parameters
Depending on your application needs, you may want to have parameters setup for your applications. Both Agent and Job applications can take parameters. The agent/job_parameters contain information about any parameters that the agent or job requires to run. They contain data_dir formatted information containing description, a required flag, type string and an optional position which is set will position the parameter in the order set 0, 1, 2, etc if not set then the parameter will be displayed in the order it’s defined. Application parameters will be saved under settings so the application should use parameters from settings.
NOTE: The hidden parameter option will not be visible to the user in the installation process but will be written under the application settings.
The following are examples of parameters that can be set for agent or the job applications respectively:
Agent Parameters example:
Example of agent parameters that can be defined for an agent application:
"agent_parameters": {
"config_file_path": {
"description": "Config file location",
"required": true,
"type": "string",
"default": "",
"setting": "config_file_path"
},
"data_dir": {
"description": "Folder location to save database files for the agent app",
"required": true,
"type": "string",
"default": "C:/bodhiAgent/node_modules/merit-agent-labor/_xmloutput/",
"setting": "data_dir"
},
"number_of_days_to_query": {
"description": "Limit query to this number of days",
"required": true,
"type": "integer",
"default": 60,
"setting": "number_of_days_to_query"
},
"interval": {
"description": "How often to execute a grind",
"required": true,
"type": "string",
"default": "every 12 hours",
"setting": "interval"
},
"local_storage_ignore_flag": {
"description": "Ignore local storage and write all data",
"required": true,
"type": "boolean",
"default": false,
"setting": "local_storage_ignore_flag"
}
}
- All Parameters have the following This example sets up four parameters: timing_expression, brink_location, accessToken and uri.
Job Parameters example:
"job_parameters": {
"timing_expression": {
"description": "How often to execute a job",
"repeat": true,
"type": "string",
"default": "60 minutes"
},
"brink_location": {
"description": "The alpha numeric string provided by the Brink POS API to identify the store location, e.g. tSm8y1TMSk7J4ZMyQBpeTg==",
"type": "string",
"required": true,
"setting": "brink_location"
},
"accessToken": {
"description": "The alpha numeric string provided by the Brink POS API to authenticate the user",
"type": "string",
"required": true,
"setting": "accessToken"
},
"uri": {
"description": "The url for the Brink POS API service e.g. https://api2.brinkpos.net/",
"type": "string",
"required": true,
"setting": "uri"
}
}
offline=true/false
Offline controls whether the container will cache application information for offline use. If offline=true and the user launches the application, any data that was previously loaded will be available when the device is offline. This will also enable queuing of data to write to the IoT Platform if the application has write permissions.
single_container_app=true/false
single_container_app tells the container know whether the app should be displayed with a menu (a collection of apps) or as a standalone single app. Bodhi Mobile has single_container_app = false. Bodhi Reveal has single_container_app = true
hide_from_global_store=true/false
hide_from_global_store controls whether the app is available to the general public to see in the global app store. Apps like Settings which cannot be removed should have hide_from_global_store=true
new_type_required=true/false
new_type_required tells the installer of the app in the global app store if the app will run 'out of the box’ or if new custom types need to be installed on the namespace. NOTE:: if new_type_required=true, troubleshooting_url should be required
screenshots{}
The screenshots array contains relative paths to screenshots which the Global App Store will use for display purposes. These files should be included in the app folder that is published and the path should be relative to the public_path.
data_dir:{}
The data_dir formatted information contains a description, a required flag, type string and an optional position which is set will position the parameter in the order set 0, 1, 2, etc if not set then the parameter will be displayed in the order it’s defined.
“autoUpdateVersion”: “false”
This flag prevents autoUpdate version of the app each time you publish. If you mark this false, you need to manually bump the version of the app each time you update it.
Example Type Definition
This is an example of an enumeration, embedded_type and custom_type.
NOTE: All enumerations must be declared first, embedded_type must be after enumerations and custom_types have to be defined after enumerations and embedded_types: This example shows the objects as folders under the application’s root directory. This is where you define your json for each type. There is a one to one correspondence of the type declared in package.json to the json defining that type in the folder under the application.
Defining your custom schema/types example:
"install": {
"new": {
"model": [
{
"type": "enumeration",
"name": "TypeName",
"object": "Enumerations/TypeName.json"
},
{
"type": "embedded_type",
"name": "InventoryPurchaseOrder",
"object": "Types/InventoryPurchaseOrder.json"
},
{ "type": "custom_type",
"name": "TypeName2",
"object": "Types/TypeName2.json"
}
],
"post-type-install": [
{"action": "POST",
"object": "Data/DataFile.json",
"path": "/resources/DataFile"
}
]
Adding Scripts and Versioning: “versions”: [..]
To make an application script available set the following in the settings section of your package.json:
- version - current script version (might be bound to the current application version)
- bundle - a jar name (by default it is “script-
.jar”) - pre-type-install - a marker for pre-install script presence. If this tag is absent - pre-install script will not be executed.
- post-type-install - a marker for post-install script presence. If this tag is absent - post-install script will not be executed.
- main - fully qulified script class name (by default it is com.bodhi.vertx.appinstaller.script.PreInstall for pre install scripts and com.bodhi.vertx.appinstaller.script.PostInstall for post install scripts:
- Example json can be found to in the javascript section >>>>>>
Template for adding scripts/versions to package.json
versions:[
{
"version": "<script_version>",
"bundle": "<jar_name>",
"pre-type-install": {
"main": "<main_class_name>"
},
"post-type-install": {
"main": "<main_class_name>"
}
]
Example of versions/scripts using seed-data:
"versions": [
{
"bundle": "installer.jar",
"post-type-install": {},
"pre-type-install": {},
"seed-data": [
{
"action": "POST",
"object": "Data/measurements.json",
"path": "/resources/InventoryUnitOfMeasure"
},
{
"action": "POST",
"object": "Data/conversions.json",
"path": "/resources/InventoryUomConversion"
}
],
"version": "new"
},
{
"bundle": "upgrade-3.0.0.jar",
"post-type-install": {
"main": "com.bodhi.vertx.appinstaller.script.DeveloperScript"
},
"version": "2.7.19"
}
]
Publishing to shop
1 - Ensure that you have your package.json, LICENSE and index.html in the root folder of your application. Note that index.html can be an empty file.
2 - Zip/compress your files. Note that the files we are compressing are the files itself not the project folder.
3 - Login to Bodhi Shop: https://tools.hotschedules.io/shop/#/my
4 - Click Publish App.
5 - Upload zip file.
6 - Verify fields are correct then publish.
7a - Verify that your application is successfully published.
7b - Make sure your file is found in https://tools.hotschedules.io/file-upload/#/files. If it doesn’t exist refer back to configuring your package.json file
Monitoring Application
Logs can be found here: https://tools.hotschedules.io/job-engine-manager/#/jobs?filters=all,all
HotSchedules Community
Do you have questions, comments or suggestions on improviements to this documentation? Please subscribe to the HotSchedules Community.