Supplyit DataStream
Jera has introduced an extension of our existing API to allow for the bulk insertion of data. At the moment this endpoint is designed for the pushing of product-related data including orders, waste, cost and pricing information. Additional data types may be supported in the future.
Table of contents
Pushing a new sales record and closing it
Pushing wastes and sales and updating pricing
Contact-Specific Product Pricing
DataStream is designed to allow many records to be pushed to a location at a single time. These records can include sales, production, purchase, and waste information. Only a single location's data is allowed per request, but multiple requests can be made in parallel (see information about throttling below).
When processing data, an attempt is made to find a corresponding record to update. Otherwise, a new record is created. For instance, if a request includes sales order information for January 1st, 2000, the system checks first to see whether a sales order already exists for the given day and, if so, will update that order. Otherwise it will create a new sales order.
When updating an existing record in the system (e.g. a waste or an order), any items on the object in Jera but not in the uploaded dataset will be removed.
The currently support record types use the following URL for the endpoint:
https://app.supplyit.com/api/v2/productstream
All requests should be PUT. Other method types are not supported at this time.
A request with an unsupported method type will receive a “405 - Method Not Allowed” response.
A PUT request with invalid JSON content will receive a “400 - Bad Request” response.
The "Accept" field is ignored as data can be retrieved only in JSON format.
Data may only be uploaded (PUT) in JSON format:
Content-Type: application/json
All requests should be encoded in UTF-8 format.
Note: Dates and times should be in ISO 8601 format, e.g. YYYY-MM-DD or YYYY-MM-DDThh:mm:ss
When including time information it is best to not include a time offset nor the UTC "zulu" time indicator. The time in the data will be considered local to the given location and any offsets are ignored. (Locations themselves can be assigned a timezone within Supplyit.)
Specifying “Accept-Encoding: gzip” in the request header will cause the response to be compressed. This is highly recommended.
Requests are currently limited to 10 per second, but this limit is subject to change without notice. The remaining requests are included in the response header [X-Jera-RemainingRequests]. If a response has that header value as "0", the next request could fail and would receive a 409 status code with the message "The allowed number of requests has been exceeded.".
The response is an array of response objects indicating actions that were taken (or, in the case of preview, actions that would have been taken). The response object structure is:
[
{
"DateTime": "2018-06-21T19:09:01.7784625Z",
"Severity": "(Debug | Info | Warning | Error)",
"Context": "",
"Message": ""
}
]
Some boolean options may be appended to the URL via the query string to indicate additional behavior.
All of these option parameters are "false" by default.
For example, to indicate you wish to open closed records, make changes, and close them again, you would use the following URL:
/api/v2/productstream?force=true&closeRecords=true
The "/productstream" endpoint expects a JSON array of objects with the following structure:
{
"recordType": "(Purchase | Sales | Work | Requisition | Waste | Cost
| SalesPrice | PurchasePrice)",
"dateTime": "0001-01-01T00:00:00",
"locationCode": "{code}",
"contactCode": "{code}",
"productCode": "{code}",
"productName": "{name}",
"catalogCode": "{name}",
"quantity": {number},
"value": {number},
"shiftCode": "{code}",
"Data": "{optional string}
}
The codes used above should reflect the data within Supplyit.
productCode, productName, and catalogCode are all required fields because if the product does not yet exist in Supplyit, it will be automatically added to the specified catalog. The catalog must already exist in Supplyit. This requires the API user be a location administrator otherwise permission will be denied.
Not all record types require all fields. For instance, a purchase order from a vendor does not require a shift. Neither does a waste.
Value represents the per-unit value of the given item, e.g. in the case of a sales record it would be the unit price.
In this simplified scenario, a single sales record is pushed to indicate that in location 448, 7 chocolate donuts were sold at 9am on June 1st, 2018 with a sales price of $.99 per donut.
Request
PUT https://app.supplyit.com/api/v2/productstream
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
{
"recordType": "Sales",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"contactCode": "RC",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"quantity": 7,
"value": .99,
"shiftCode": "Production"
}
Response
[{
"DateTime": "2018-06-21T21:49:31.4242803Z",
"Severity": "Info",
"Context": "448",
"Message": "Begin processing data"
}, {
"DateTime": "2018-06-21T21:49:31.5742029Z",
"Severity": "Info",
"Context": "448",
"Message": "The following records exist in the source data:(Sales: 1)"
}, {
"DateTime": "2018-06-21T21:49:31.6152033Z",
"Severity": "Info",
"Context": "SalesOrder order 6/1/2018",
"Message": "Creating new SalesOrder"
}, {
"DateTime": "2018-06-21T21:49:31.7722146Z",
"Severity": "Info",
"Context": "SalesOrder order 6/1/2018",
"Message": "Finished importing data for 448"
}
]
Note the addition of the "closeRecords=true" to the query string
PUT https://app.supplyit.com/api/v2/productstream?closeRecords=true
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
{
"recordType": "Sales",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"contactCode": "RC",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"quantity": 7,
"value": .99,
"shiftCode": "Production"
}
Here 3 records are pushed: two sales items (Chocolate Donut and Egg Sandwich) and a waste item indicating that 2 egg sandwiches were thrown away and that each was valued at $2.99.
Request
PUT https://app.supplyit.com/api/v2/productstream
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
[{
"recordType": "Sales",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"contactCode": "RC",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"quantity": 7,
"value": .99,
"shiftCode": "Production",
"recordType": "Sales",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"contactCode": "RC"productCode": "12345",
"productName": "Egg Sandwich",
"catalogCode": "Bakery Items",
"quantity": 5,
"value": 3.99,
"shiftCode": "Production",
"recordType": "Waste",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"productCode": "98765",
"productName": "Egg Sandwich",
"catalogCode": "Bakery Items",
"quantity": 2,
"value": 2.99,
"shiftCode": "Production"
}]
Here the same 3 records from the previous example are pushed but the optional parameters updatePrices and UpdateCosts is set to true. This will perform the same update as the previous example and will also update the registered sales price for the two items and it will update the cost for the wasted item.
Request
PUT https://app.supplyit.com/api/v2/productstream?updateCosts=true&updatePrices=true
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
[{
"recordType": "Sales",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"contactCode": "RC",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"quantity": 7,
"value": .99,
"shiftCode": "Production",
"recordType": "Sales",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"contactCode": "RC"productCode": "12345",
"productName": "Egg Sandwich",
"catalogCode": "Bakery Items",
"quantity": 5,
"value": 3.99,
"shiftCode": "Production",
"recordType": "Waste",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"productCode": "98765",
"productName": "Egg Sandwich",
"catalogCode": "Bakery Items",
"quantity": 2,
"value": 2.99,
"shiftCode": "Production"
}]
Pricing -- either sales or purchase -- can be set on a product. This is used to set the price of new orders generated within Supplyit. Pricing can be up to 4 decimal places.
PUT https://app.supplyit.com/api/v2/productstream
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
[{
"recordType": "SalesPrice",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"value": 9.9999
}]
PUT https://app.supplyit.com/api/v2/productstream
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
[{
"recordType": "PurchasePrice",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"value": 9.99,
"contactCode": "Vendor1234"
}]
PUT https://app.supplyit.com/api/v2/productstream
Accept: application/json
Authorization: f9f69d68-c2e2-47e0-b04b-82ee5ea1eb46
X-Jera-LocationCode: 448
Content-Type: application/json
[{
"recordType": "Cost",
"dateTime": "2018-06-01T09:00:00",
"locationCode": "448",
"productCode": "595959",
"productName": "CHOCOLATE DONUT",
"catalogCode": "Bakery Items",
"quantity": 1,
"value": 9.9999
}]
Please see https://help.jeraconcepts.com for more information about Supplyit or to contact Support.