RESTful-JSON-API Reference

The KassaForte API uses HTTP verbs and a RESTful endpoint structure. HTTP Basic Authentication in combination with SSL/TLS is used for securly identifing a KassaForte-Webshop. All requests and responses are formated in JSON. JSON-Schemas (draft-04) are available for every request and response.

Table of Contents

API Operations

This API is intended for use with a webserver or mobile app to recieve all data needed to build a working shop-solution. This includes a complete menu, data about open hours, delivery costs and much more. All data can (and should) be stored localy, the noteable exception being "Get Shop Infos", which should be updated frequently, at least during open hours.

The API is available in the live-environment and a sandbox-environment for testing. To access the live-environment use the domain webservices-api.kassaforte-systems.com, to access the sandbox use webservices-api-sandbox.kassaforte-systems.com.

A REST operation is performed by sending a request with a valid HTTP method to one of the endpoints defining the operation. For example to request the menu of a shop from the live-environmet you send the following request:

GET https://webservices-api.kassaforte-systems.com/v1/menu

The same request on a sandbox-shop would be:

GET https://webservices-api-sandbox.kassaforte-systems.com/v1/menu

Authentication

To authenticate your request you will have to connect to the api using a https-connection. Attempts to connect via http will lead to 403 Forbidden-errors. For now authentication will be handled via HTTP Basic Authentication. The username and password will be a random string containing upper and lower case letters, numbers and symbols and will be provided by us.
Authentication is required for every operation.

Possible Operations

General server responses

The server responds with the aid of HTTP-Statuscodes to inform you about the status of your request. Some responses are common among many operations, these are described here:

200 Ok
The standard response if everything was alright.
400 Bad Request
The request body could not be validated against the corresponding JSON-Schema.
401 Unauthorized
Either your username was not recognized or the password differed from the one on our server.
403 Forbidden
You tried to access the endpoint without SSL.
404 Not Found
The endpoint of the request is unknown.
405 Method Not Allowed
The HTTP-Method used to adress the operation is not valid. A list of valid methods is supplied in the HTTP-Accept header.
500 Internal Server Error
An internal error has occured. Sadly there is nothing you can do. The Admin has most likely been automaticly informed about the error.

Get Shop Infos

GET https://{DOMAIN}/v1/infos

This operation shows you important information about the operational status of the shop. Therefore this data should be updated frequently to be able to inform your users in time about changes. The currently transmitted infos are:

lastMenuRefresh
The date of the last update of the menu.
lastOpenTimesRefresh
The date of the last update of the open hours.
lastDeliveryCostRefresh
The date of the last update of the delivery costs definition.
connectionStatus
The current status of the KassaForte->Webserver-connection. If the connection is interrupted during open hours, you should consider not sending orders and informing your users until the connection is reestablished. The API-Server will accept orders, even if the connection is interrupted, so you can decide yourself, how you want to deal with this situation.
shopOpenStatus
An object with the two keys delivery and pickup. This shows you if the shop was closed manually for any of the delivery types. This may be nessessary, if a shop has a pickup-serivce at noon and in the evening, but delivery-service only in the evening. Or delivery service is suspended due to icy roads.
waitingTimes
The time in minutes a customer is likely to wait, until its order is finished. As with shopOpenStatus has two values for delivery and pickup.
unavailableProducts
A list of item numbers, that are currently unavailable. Those items should not be omitted when the menu is presented to the user, as they are still part of the menu, but be marked as unavailable. Ordering unavailable items will result in validation errors on sending

This operation doesn't need a request body, just send an authenticated request to the endpoint to recieve the data.

Get Open Hours

GET https://{DOMAIN}/v1/openhours

This operation gives you a list of all open hours for each day, as well as a configuration when to start and end accepting orders.

openingtimes
The index of this array represents the day of the week, starting with 0 for Monday, 1 for Tuesday and so on. Index 7 contains the times for holidays.
acceptStart
Defines the number of minutes the app should start accepting orders before the shop is actually opened.
acceptEnd
Defines the number of minutes the app should stop accepting orders before the shop is actually closed.

This operation doesn't need a request body, just send an authenticated request to the endpoint to recieve the data.

Get the Menu

GET https://{DOMAIN}/v1/menu

With this operation you get access to the complete menu of the shop. The response will contain information about categories, products, menus, ingredients, choice-ingredients, sizes, special offers and general properties. Please refer to the schema and example for more detailed information.

This operation doesn't need a request body, just send an authenticated request to the endpoint to recieve the data.

Get Delivery Costs

GET https://{DOMAIN}/v1/deliverycosts

This operation will give you access to the delivery costs configuration for the shop. As there are many different ways to deal with delivery costs we currently support two differnt ways of determining delivery costs in the App:

  1. via Zip-Code and
  2. via Distance
As both ways differ slightly in their requirements, the response will differ, depending on the type. Take a look at the schema and the two examples for more details.
If no delivery costs shall be applied, this operation will just return "null".

General

Some fields are common for both types, these will be explained here.

minimumOrderValue
The minimum amount that the order should have, before it can be send.
deliveryCosts
The actual costs for the delivery. Has to be added, after the minimumOrderValue-check.
freeDeliveryAsOf
The amount when delivery costs should not be applied anymore. The value is 40, the sum of the cart is 36, then delivery costs apply. Another product is added to the cart, raising the sum to 40 or higher, then no more delivery costs shall be raised. If the value is negative (usually -1), delivery costs always apply.

Zip-Code

The delivery costs will be determined by the zip-code chosen by the user. The chosen id of the list-entry has to be transmitted, when you send the order (more info here: Post an Order).

id
An unique identifier for this zip-code. Needed for validation on the server. If an id with value -1 exists, delivery to other places than defined is possible with the values provided by this id.
zipcode
The zip-code
city
The city this zip-code belongs to.
district
The district of the city this zip-code belong to.
Please note, that it is possible to have multiple definitions for the same zip-code (hence the usage of an id).

Distance

The delivery costs will be determined by the distance form the shop to the customer. How you compute this value is up to you, but we suggest using a routing service like Google Maps. The computed distance has to be transmitted, when you send the order (more info here: Post an Order).
The distance type just has one extra key per definition:

tillDistance
Defines the maximum distance for which this definition applies.
You should always use the closest definition that can be applied. E.g. you have three definitions with values 1000, 2000 and 4000, the distance is 1439. In this case, you use the 2000 defintion, because the 1000 definition cannot be applied and 4000 is not the closest possible definition, as 2000 is between 1439 and 4000.

This operation doesn't need a request body, just send an authenticated request to the endpoint to recieve the data.

Orders

The order-operation is currently the only endpoint with different behavior depending on the HTTP-verb.

Post an Order

POST https://{DOMAIN}/v1/order

With this operation you can submit an order to the webshop. The order will be validated based on the request schema and the data on the server. This means, that it might happen, that an order will be rejected by the server with a 409 Conflict, because an update of the menu happend in the time between your last update of Get Shop Infos and the submission of the order. Please be prepared for this case.

Operation-specific server responses
201 Created
The order has been successfully validated and is currently awaiting transmission to KassaForte. The response body contains an <order-id> for use with Get Order status.
409 Conflict
The data submitted in the request differs from the data on the server (e.g. unknown ingredient-id). The response-body will contain more information on the error (see Error Codes), so you may be able alter the request, so it validates. It may be nessessary to re-request the menu, if it was updated in the meantime. A complete list of all possible errors can be found at the end of this document.

Get Order status

GET https://{DOMAIN}/v1/order/<order-id>

With this operation you can request the current status of an order. Just replace <order-id> in the endpoint with the order-id supplied by the resonse of Post an Order.

This operation doesn't need a request body, just send an authenticated request to the endpoint to recieve the data.

Operation-specific server responses
400 Bad Request
The supplied order-id did not match the expected format (14-digits).

Check a Discount Code

GET https://{DOMAIN}/v1/discountcode

With this operation you can confirm the validity of a discount code and recieve information about its configuration.
There are currently three types of discount codes:

amount
An amount, by which the sum of the cart should be reduced. The exceptions must be respected.
percent
A percentage, by which the sum of the cart should be reduced. The exceptions must be respected.
article
A combination of item-number and size, which should be added to the cart without charge.
The exceptions-list specifies categories that are excluded from the discount. That means the prices of products from these categories will not be reduced by a percent-discount and the remaining amount of an amount-discount will be discarded, if it would reduce the price of an protected product.
On article-discounts the exceptions-list will be omitted.

Check a Coupon

GET https://{DOMAIN}/v1/coupon

With this operation you can confirm the validity of a coupon. You send the coupon-number and the corresponding verify-code and get the coupon-number and the remaining amount of the coupon in response.
This amount has to be subtracted from the sum of the cart without exceptions. If the coupon has a higher value than the sum, the coupon will stay valid with the reduced value.

Operation-specific server responses
404 Not Found
No coupon with this number could be found.
409 Conflict
The verifyCode didn't match the one stored in the database.

Send a Contact Request

POST https://{DOMAIN}/v1/contactrequest

This operation enables you to send contact requests directly to KassaForte.

Error Codes

This API validates every order, that is submitted to it. It is possible that the validation fails, if there was an update of the menu or the date has changed (discount code may expire) or something similar. We try to make it possible for you to react to those situations as good as possible.
Every validation error has its own error-code and a (hopefully) meaningful description. Depending on the situation, the description may contain the item-number or id of the element, that caused the error, in a parseable manner (surrounded by #).

<name> are placeholders for the corresponding variable

1xx Error occured while validating the order

101
No choices have been supplied for #<item-no>#, but choices are mandatory
102
Computed overall sum of #<our-sum># differs from send sum #<your-sum>#
103
Invalid payment method #<payment-method>#

2xx Error occured while validating a article

201
Article #<item-no># has no price for size #<size-id>#
202
Unknown article #<item-no>#
203
Computed price of #<our-price># differs from send price #<your-price>#
204
Ingredient #<ingredient-id># is not allowed in category with id #<category-id>#
205
Invalid choice #<choice-id>#

3xx Error occured while validating a menu

301
Menu #<item-no># has no price.
302
Unknown menu #<item-no>#
303
Expected item count of <expected-count> differs from actual itemcount of <actual-count>
304
Computed price of #<our-price># differs from send price #<your-price>#
305
Can't find a match for article #<item-no># in size #<size-id># in categories of menu #<item-no>"#
306
Article #<item-no># is not allowed in menus.

4xx Error occured while validating a ingredient

401
Ingredient #<ingredient-id># has no price for size #<size-id>#
402
Unknown ingredient #<ingredient-id>#

5xx Error occured while validating a discount-code

501
Unknown discount #<discount-code>#

6xx Error occured while validating delivery costs

601
Unknown delivery cost type
602
Wrong delivery cost type #<delivery-type>#, extected type #<delivery-type>#
603
Unknown zipId #<zip-id>#
604
Delivery allowed only to defined zipIds
605
Minimum order value of #<minimum-sum># not reached with order value of #<your-sum>#
606
Computed delivery costs of #<our-sum># differs from send delivery costs #<your-sum>#
607
No data defined for distance #<distance>#

Changelog

2015-12-14
MENU: Added "minimumOrderValue" to "categories". This indicates if producty of this category shall be included in the computation of the minimum order value. This is an integer-field so you can just multiplicate its value this the sum of the product.
2016-04-26
ORDER: Changed type of payment method from string to integer, for easier addition of new payment types. The payment method is now the index of this list
MENU: Added Allergens and Additives to the Menu. Both are added as comma-separated lists of indexes to each product and indexed lists to the menu itself.
MENU: Fixed some bugs with menus and choices for products.