Introduction
Welcome to VendNovation's Vendor API! You can use our API to build custom interfaces to your data within VendNovation's system.
To help you get started in your development, we provide a Postman collection that you can import. Download it here (right click and Save Link As). Our postman collection makes use of collection level variables which you can learn about here. The variable names have already been defined and inserted throughout the collection, you just need to enter your values.
By reading and using this documentation, you agree to these terms.
Concepts
API Access Tokens
The Vendor API uses AWS api tokens to control access to the api and to manage rate limiting. If you do not have a token, email us!. To use your token please include a header like x-api-key: accessToken. This is required on all requests. We have a route to help you test that this is setup properly. See the Token Test route for more information.
If you do not have a token, perform the following:
- Create one or more User(s) within the Organization that requires API access. a. We suggest api@organizationName.com for the login email. b. Set a strong password - the password for this user will be used in conjunction with an organization specific API key to authenticate against the API.
- Contact api-request@vendnovation.com and provide your Organization Name and the login email(s) of those users you wish to enable API access for.
- VendNovation will enable API access for those Users and send you your Organization specific API Key.
Usage Plan Details
Your API token is attached to a usage plan with some limitations placed on it. The limitations are:
All new API access keys are limited to the following restrictions:
| Limits | |
|---|---|
| Rate | 20 requests per second |
| Burst | 100 requests |
| Quota | 5,000 requests per day |
Proper call optimization should allow you to stay within the limits. Remember that all calls support retrieving multiple data sets by ID simultaneously
Request Filter
Most routes support a universal request filter to control the data that you receive back in the response. Not all routes support all features of the request filter, so on any given route's documentation page, you will see a table like below, indicating what request filter options are honored by that route.
| Filter Name | Type | Default Value | Description |
|---|---|---|---|
| startDate | DateTime | Current UTC DateTime - 7 Days | Excludes all records that occurred before this date |
| endDate | DateTime | Current UTC DateTime - 7 Days | Excludes all records that occurred after this date |
| includeDeleted | boolean | False | Includes deleted records that are normally excluded from the response |
| organizationIds | List |
null | Filter results to only the specified Organization or their child records |
| accountIds | List |
null | Filter results to only the specified Accounts or their child records |
| siteIds | List |
null | Filter results to only the specified Sites or their child records |
Specifying a request filter not honored by that route will not cause an error, but will also have no effect. Additionally, you can specify multiple ID filters if they are supported by the route, and they will all be applied.
DateTime Handling
A Note on Time Zones
When working with DateTime filters, there are additional considerations regarding timezones. The DateTimes in our systems are stored in the local time as configured for the site/machine. The stored time for things like transactions report is the local time reported by the machine. As a result, to make working with DateTimes easier if you are not using the website for data tracking, you may consider configure your sites to be UTC.
StartDate and EndDate Clamping
When you provide a StartDate and/or EndDate in your request filter, the dates you provided will not necessarily be the dates used in your request. We apply a series of clamping rules to your DateTimes to restrict your maximum search range to know more than the maximum range (which varies between calls as performance allows) as well as generate either or both DateTimes if they were not both provided.
Here is a breakdown of this to help you understand how this works
| StartDate Provided | EndDate Provided | Result |
|---|---|---|
| Yes | Yes | Your end date will be modified if the time span between provided start and end is larger than the maximum range |
| Yes | No | Your end date will be set to maximum range number of days from your start date |
| No | Yes | The start date will be generated as your end date minus range maximum |
| No | No | End date will be generated as DateTime.Now, and your start date will be range maximum days earlier |
If applicable, the API response will include additional headers to help you detect when we have modified date-time search parameters.
SearchRangeStartDate - will contain the modified search start date and time, as applicable
SearchRangeEndDate - will contain the modified search end date and time, as applicable
Also of note, the time portion of the DateTime is optional. If omitted, StartDate will be given a time of 00:00:00 and EndDate will be given a time of 23:59:59.
Authentication
API Key Test
Request Body
None
Response body on failure
{
"message": "Forbidden"
}
Response body on success
Access token was valid
This endpoint helps you test that your access tokens are set in your header correctly.
POST https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/token_test
This endpoint does not require you to be authenticated. If you POST to it with your access token configured correctly it will tell you that your token is valid. Otherwise it will respond with a forbidden message. This is a great place to start your api development!
Get Login Token
Your request body should look like
{
"username": "me@domain.tld",
"password": "password"
}
You will receive a JSON response like
{
"accessToken": "9f57c00f-a92d-49e5-86fd-0052b56e0161",
"userName": "me@domain.com",
"issued": "9/3/2020 11:17:40 PM",
"expires": "9/6/2020 11:17:40 PM"
}
Given a valid Vendor login returns an access token authenticating you for data retrieval. Tokens are good for three days from generation. It is worth noting that all credentials for an organization are not created equal as what data you can retrieve is tied to the credentials permissions within that organization.
HTTP Request
POST https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/authenticate
Filter Parameters
None supported
Organizations
Get Organizations
Request body
{
// optional list of IDs for the organizations you want to retrieve
"requestFilter": {
"organizationIds": [ ]
}
}
Response body
[
{
"Id": 1,
"AdministrativeOrganizationId": 3,
"Name": "Generic Vending",
"Address": "123 Some St. Anytown, USA 12345" ,
"Contact": "John Smith",
"Type": "Manager"
}
]
Return a list (or a subset) of Organizations the user has access to.
| Attribute | Type | Description |
|---|---|---|
| Id | integer | Organization Id |
| AdministrativeOrganizationId | integer | Managing organization |
| Name | string | Organization name |
| Address | string | Organization address |
| Contact | string | Organization Point of Contact |
| Type | string | Whether a client or managed organization |
HTTP Request
POST https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/organizations
Request Filters Honored
| Filter Name | Type | Description |
|---|---|---|
| organizationIds | integer | Filter results to only the specified Organization or their child records |
Accounts
Get Accounts
Request body
{
"requestFilter": {
"organizationIds": [3],
"accountIds": []
}
}
Response body
[
{
"Id": 2,
"Name": "John Vending",
"VendorOrgId": 3,
"ClientOrgId": 13,
"IsVisible": true,
"Contact": "Jane Smith",
"TimeZone": null
},
{
"Id": 3,
"Name": "Smith Vending",
"VendorOrgId": 3,
"ClientOrgId": null,
"IsVisible": true,
"Contact": "Tom Smith",
"TimeZone": null
}
]
Get a list (or subset) of Accounts associated with an Organization.
| Attribute | Type | Description |
|---|---|---|
| Id | integer | JSON block ID |
| Name | string | Name of the Account |
| VendorOrgId | integer | Id of the Organization that manages the Account |
| ClientOrgId | integer | Account ID |
| IsVisible | boolean | Whether the Account is visible or not in the Client Portal |
| Contact | string | Account Point of Contact |
| TimeZone | string | Your accounts configured timezone |
HTTP Request
POST https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/accounts
Request Filters Honored
| Filter Name | Type | Description |
|---|---|---|
| organizationIds | integer | Filter results to only the specified Organization or their child records |
| accountIds | integer | Filter results to only the specified Accounts or their child records |
Sites
Get Sites
Request body
{
"requestFilter": {
"organizationIds": [3],
"accountIds": [49,3],
"siteIds": [205]
}
}
Response body
[
{
"Id": 205,
"AccountId": 49,
"OrgId": 3,
"Name": "ATS",
"Contact": null,
"CommissionPercentage": null,
"IsActive": true,
"TimeZone": "Pacific Standard Time",
"IsEnabled": false,
"MaxChargePrice": 5,
"BillingAddress": "ATS\r\n6300 Merrill Creek Pkwy\r\nSuite A-100\r\nEverett, WA 98203",
"ShippingAddress": "ATS\r\n6300 Merrill Creek Pkwy\r\nSuite A-100\r\nEverett, WA 98203",
"MaximumMeterSalesJumpAllowed": 500,
"CommissionTerms": "Net10",
"ExternalAccountTerminalId": null
}
]
Get a list (or subset) of Sites belonging to an Organization.
HTTP Request
POST https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/sites
Request Filters Honored
| Filter Name | Type | Description |
|---|---|---|
| organizationIds | List |
Filter results to only the specified Organization or their child records |
| accountIds | List |
Filter results to only the specified Accounts or their child records |
| siteIds | List |
Filter results to only the specified Accounts or their child records |
| includeDeleted | boolean | Include deleted records that are normally excluded from the response |
Create Sites
Request Body
{
"sites":
[
{
"Id": 196,
"AccountId": 11,
"OrgId": 3,
"Name": "Clearwire4",
"Contact": null,
"CommissionPercentage": null,
"IsActive": true,
"TimeZone": "Pacific Standard Time",
"IsEnabled": false,
"MaxChargePrice": 5,
"BillingAddress": "Clearwire\r\nPO Box 1726\r\nWoodinv, WA 98072",
"ShippingAddress": "Clearwire\r\nPO Box 1726\r\nWoodinv, WA 98072",
"MaximumMeterSalesJumpAllowed": 500,
"CommissionTerms": "Net10",
"ExternalAccountTerminalId": null
}
]
}
Response body
// This is a list of the created site's IDs
[
1673
]
Creates a new Site within a specified Organization. Below are the required fields and anything not filled out will be created as null.
HTTP Request
PUT https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/sites
Request Filters Honored
None.
Update Sites
Request body
{
"sites":
[
{
"Id": 196,
"AccountId": 11,
"OrgId": 3,
"Name": "Clearwire5",
"Contact": null,
"CommissionPercentage": null,
"IsActive": true,
"TimeZone": "Pacific Standard Time",
"IsEnabled": false,
"MaxChargePrice": 5,
"BillingAddress": "Clearwire\r\nPO Box 1726\r\nWoodinv, WA 98072",
"ShippingAddress": "Clearwire\r\nPO Box 1726\r\nWoodinv, WA 98072",
"MaximumMeterSalesJumpAllowed": 500,
"CommissionTerms": "Net10",
"ExternalAccountTerminalId": null
}
]
}
Response body
// Note this is just echoing back what was specified
[
{
"Id": 196,
"AccountId": 11,
"OrgId": 3,
"Name": "Clearwire5",
"Contact": null,
"CommissionPercentage": null,
"IsActive": true,
"TimeZone": "Pacific Standard Time",
"IsEnabled": false,
"MaxChargePrice": 5,
"BillingAddress": "Clearwire\r\nPO Box 1726\r\nWoodinv, WA 98072",
"ShippingAddress": "Clearwire\r\nPO Box 1726\r\nWoodinv, WA 98072",
"MaximumMeterSalesJumpAllowed": 500,
"CommissionTerms": "Net10",
"ExternalAccountTerminalId": null
}
]
Updates a Site within a specified Organization. Below are the required fields and anything not filled out will be created as null. Note that Sites can be deleted or undeleted via this method by setting the IsEnabled flag.
Note that IsActive and Name cannot be changed via an update operation at this time.
HTTP Request
PATCH https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/prod/sites
Request Filters Honored
None.
Site Definition
| Attribute | Type | Description |
|---|---|---|
| Id | integer | JSON block ID |
| AccountId | integer | Account ID that the Site belongs to |
| OrgId | integer | Organization ID that the Site belongs to |
| Name | string | Name of the Site |
| Contact | string | Name of the Point of Contact for the Site |
| CommissionPercentage | integer | |
| IsActive | boolean | Indicates whether the Site is active or inactive |
| TimeZone | string | Time zone that the Site is set to |
| IsEnabled | boolean | Indicates whether the Site is enabled in Client UI |
| MaxChargePrice | integer | Maximum charge anticipated for machines assigned to Site |
| BillingAddress | string | Billing address for the Site |
| ShippingAddress | string | Shipping address for the Site |
| MaximumMeterSalesJumpAllowed | integer | Maximum meter sales jump allowed |
| CommissionTerms | string | Commision terms period. See below for valid options. |
| ExternalAccountTerminalId | string | ID to configure Site with external POS system |
Valid CommissionTerms values
- PrePaid
- Net10
- Net15
- Net30
- Net45
- Net60
Transactions
Get Transactions
Request body:
{
{
"includeDeleted": false,
"startDate": "0001-01-01T00:00:00",
"endDate": "0001-01-01T00:00:00",
"organizationIds": null,
"accountIds": null,
"siteIds": null
},
"reportConfig": {
"orgId": 0,
"filterBy": 0,
"filterValue": null,
"subtotalColumn": 0
}
}
Sample response (this is always an array!):
[
{
"Date": "0001-01-01T00:00:00",
"SlotId": 0,
"SiteName": "Site name",
"MachineName": "Machine name",
"MachineLocation": "a place a machine is",
// See the TranasctionType definition table
"Type": "Cash",
"ProductName": "My cool product",
"ProductUpc": "ABC123",
"Size": "10 LBS",
// This represents a percentage. 9% will be reported as 0.09
"TaxRate": 0.0,
// This represents a percentage. 9% will be reported as 0.09
"Commission": 0.0,
"Number": 0,
// This is the total price we charged for the transaction
"TotalPrice": 0.0,
// This is the price we charged per unit
"UnitPrice": 0.0,
"CustomerName": "Bob Smith",
"CustomerNumber": "#1234"
}
]
This endpoint retrieves transactions.
HTTP Request
POST https://s1i0m68usk.execute-api.us-west-2.amazonaws.com/Prod/transactions
Query Parameters
| Parameter | Default | Description |
|---|---|---|
| page | 1 | The page of results you want to retrieve. |
| size | 50 | How many transactions you would like per page. Clamped to a maximum of 2000. |
Request Filters Honored
| Name | Effect |
|---|---|
| StartDate | Filters out transactions that ocurred before this DateTime. See DateTime clamping for me information. |
| EndDate | Filters out transactions that ocurred after this DateTime. See DateTime clamping for me information. |
Please note that the maximum time range for the transactions report is 365 days.
TransactionsReportConfig
In addition to the supported RequestFilter options, the transactions report requires an additional configuration object. This object and all fields in it are mandatory.
| Name | Type | Effect |
|---|---|---|
| OrgId | int | If present only returns results from the organization with the specified ID. |
| FilterBy | string | This allows you to select an additional thing to filter transactions by. See the FilterBy table for options, values, and effects. |
| FilterValue | string | The value you want to provide to your selected value. This should be parsable as a number unless you are filtering by product or employee which are alphanumeric. |
| SubtotalColumn | string | Generate additional subtotal records totaled by your specified value. See the SubtotalBy table for values. |
Subtotal
SubtotalColumn creates subtotal records that will be part of your return value with the subtotal being calculated based on the specified column. It is unlikely that you want to set this to anything but NoSubtotal! Valid values are:
- NoSubtotal
- Account
- Site
- Machine
- ProductNumber
- EmployeeNumber
FilterBy and FilterValue
FilterBy allows you to narrow your returned data set to only transactions that occur at the specified FilterBy level with the specified FilterValue. Note that all FilterValue values are to be provided as a string, but that string MUST be parsable as the specified type.
| FilterBy Name | FilterValue Type |
|---|---|
| NoFilter | Empty string (other values will be ignored). |
| Account | Integer account ID. |
| Site | Integer site ID |
| Machine | Integer machine ID. |
| Product # | Alphanumeric product number. |
| Employee # | Alphanumeric employee number. |
Response Object
TransactionType
The Type is internally stored as an enum. It s possible values are:
- Credit
- Cash
- Account
- Unknown
Legal
© 2020 VendNovation, LLC - Proprietary and confidential. Do not distribute without express permission.