Fiidmi API Overview

This page provides description of various generic things about API.

Versioning

Patch versions (1.0 to 1.0.x, for example) are meant to be backwards and forwards compatible, like fixing bugs or improving this documentation. Minor versions are meant to be backwards compatible to point of old major version.

API urls contains only major and minor versions. Patch versions (last .3 of 1.2.3) are not present.

An application using 1.1 will be compatible with API version 1.9, but application using new features of 1.9 doesn’t work with API version 1.8.

API URL

Following is complete URI for login action:

https://api.fiidmi.fi/1.0/account/login

API key provided from registration form works initially only on test environment. Please contact us when your application is ready for deployment.

Where 1.0 is version of the API and /account/login tells the action used in request.

Test environment

There is test environment available:

https://testapi.fiidmi.fi

Which otherwise behaves like the release version but it may have support for newer API and/or experimental features. Orders created using test API won’t be delivered to restaurants.

Remember to include version in test API request, like https://testapi.fiidmi.fi/1.0/account/login.

Test environment does not have production data.

Requests and responses

API must be used with HTTP POST. Answers are in JSON format. HTTPS (SSL) is strongly preferred over HTTP. Consider using HTTP gateway as unsupported way to access data (insecure as passwords go plaintext, so it is going away soon).

All requests must be encoded with UTF-8.

If JSON is not familiar, see here: http://www.json.org/.

Error conventions

API employs error structure that contains localized string, error label, label related information and possibly debug information.

[
  {
    "label":"WRONG_DELIVERY_PRICE",
    "given_delivery_price":4.90,
    "calculated_delivery_price":4.89,
    "message":"Localized message about wrong delivery fee that can be shown to the customer",
    "debug":"restaurant_id: 1 or other useful information when things go haywire"
  },
  { ".." }
]

Some of error labels may be recoverable, like wrong price calculation, in which case client could just ask customer if new price is ok and resend order with that price. Mostly errors does not have this kind of behaviour; they are always documented case-by-case.

Unless there is clear benefit from using labels to recognize the error, often just showing the error and aborting/retrying the request is what can be done.

Good guideline is to show the message in the error always when it is possible. If it is not, automatically doing what error tells to do is the way to go.

There is one error that may happen at any time:

Label Additional data Description
INTERNAL_ERRORNoneSometimes, our error handling is not enough good, and it goes to this one. Most fatal errors, like syntax errors, does not even throw this one, but just echoes some garbage.

Session management

Users are identified by a value session_id that is passed in the requests. For some requests, like /account/register, session_id (and that way API authentication) is not needed. Requests that needs session_id present have session_id in their parameter list.

For example, client sends request /account/login with POST values username="test" password="user" and server responses with username="test" session_id="secret_value"

POST nameValue
session_id"secret_value"

Session id is obtained with sending api_key and secret as described at chapter Authentication, few lines below this.

Session related errors

There is some errors that could always happen from session handling.

See error conventions section for explanation how error system works.

Most of these are API level errors; if they happen, either Fiidmi API service or the client is broken.

Label Additional data Description
API_KEY_SECRET_UNSETNone If api_key or secret is unset when trying to login, this is returned.
API_KEY_IN_WRONG_ACTIONNone Tried to supply api_key with action that was not /action/login.
SESSION_NO_USER_FOUNDNone No user found for the username that was given with login action.
SESSION_PERMISSION_DENIEDNone This is returned if api_key and secret are not valid. They have either been expired, deleted or you are trying to use wrong credentials. Remember to hash credentials with sha512.
INVALID_SESSION_IDNone This most likely means that customer’s session has expired, and customer needs to log back in. The message returned should be shown to customer, and maybe automatically shown / redirected the login page.

Language

Primary language is English.

Note that ingredient and product names with other static data returned in responses are hardcoded to Finnish and there is no way to translate them. In that sense an english version of a client can’t be completely translated, though basic stuff like menus in English may benefit our English-based users.

Customer’s locale can be defined at /account/login action. Please see its page for more information.

Authentication

For use of the API, api_key and secret must be submitted to identify client and recognize the user.

POST nameValue
username"test"
password"user"
api_key"private_api_key"
secret"secret_key_for_api_key"

username and password are “default” parameters from login request, and api_key and secret are used to specify the API used.

session_id is returned as part of answer that is then used in requests to identify the user that has logged in to the system. In future requests api_key and secret are not used (and so doesn’t need to be in requests), session_id instead is used to recognize users. See Session management for more info.

Invalid API key results to "Permission denied" error.

NOTE: API key and secret should be hashed with SHA512.

Workflow

Since the client virtually does not know anything in advance, about everything must be asked from customer. Things like where customer wants to order be delivered, from which restaurant and contents of the order. There is some different ways to implement these features, but basic workflow is same for everything.

For example locating restaurants for the customer can be done using coordinates (from GPS, for example) or by address customer has manually inserted or by city name, which returns all restaurants of city. There is more information of those in /restaurant/list page.

Normal workflow for a customer

  1. customer opens the client -> a page where customer can insert a location for restaurant list is shown (or similar)
  2. customer inserts wanted location in way or another -> server returns list of restaurants
  3. customer chooses a restaurant -> server returns restaurant’s data
  4. customer chooses products she wants to order -> nothing is sent to server; client stores chosen data
  5. customer goes to order creation page (create order)
  6. customer specifies delivery method, chooses delivery address, payment method and other order related information
  7. customer presses make order button -> /restaurant/make_order page. call is made with given data
  8. ( In case of prepaid order, server returns an URL that needs to be opened in a browser of some form. There customer can do the actual payment. )
  9. upon successful payment (or cash order), customer is shown a thank you page of successful order

In essence, customer chooses location, then restaurant, then products and then does the order. There might be need for different kind of logic for example for restaurant chains, where you already know what products belongs to the menu.

Chain specific workflow for customer

For some chains, most notably Kotipizza, all restaurants of a chain contains same information, aside from open and delivery times and similar restaurant information. For those chains, client might just offer a menu where to order from.

  1. customer opens the client -> menu is shown
  2. customer chooses products she wants to order -> nothing is sent to server; client stores chosen data
  3. customer goes to order creation page (create order)
  4. customer specifies delivery method, chooses delivery address, payment method and other order related information
  5. customer chooses the restaurant where she wants to do the order (list of them can be fetched using delivery address)
  6. customer presses make order button -> /restaurant/make_order page. call is made with given data
  7. ( In case of prepaid order, server returns an URL that needs to be opened in a browser of some form. There customer can do the actual payment. )
  8. upon successful payment (or cash order), customer is shown a thank you page of successful order

There is few things to note. Client must originally query specific restaurant’s data, immediately before menu is shown to customer (to get the data to show in menu). And when customer is making an order, using delivery address, client can receive all restaurants close to client’s address and allow customer to choose from those restaurants.

At this stage, validation of open and delivery times must be done, and customer accordingly informed whether customer can be do the order now or at all. For example, instruct customer to choose another restaurant, specify another delivery address, choose fetch order or do alternative delivery time, if there is some reason delivery order can’t be made now, if customer requested for one.

Id conversion

Because restaurant data initially fetched contains ids that do not belong to the restaurant customer is actually creating the order to, there must be some kind of conversion. There is few solutions for this problem.

One solution is when client stores names of the products, ingredient changes and so on, and when correct restaurant is chosen ( and order submitted to avoid extra conversions in case of it’s expensive operation) correct restaurant’s data is fetched, data is looped through and wrong ids are replaced with correct ids.

This requires some work from client, so there is a possibility for automatic mapping on server side. This won’t be allowed to clients to automatically do due it’d allow clients to do any orders to any restaurant and that’s not really a good thing. For this reason it is possible to bind specific api key to have ability use validate_against_restaurant_id attribute to specify the restaurant that contains ids that are submitted in make_order call.

This binding is strictly api key specific and only works for certain set of restaurants. For example, for Kotipizza chain, only Kotipizzas can be passed as restaurant_id when Kotipizza’s validation restaurant is specified in validate_against_restaurant.

Please contact us if you need such support, or if you’d want to implement a workflow that differs from general ideas described here.

Payments

Information related payments can be found at payment method section at /restaurant/metadata.

Times and dates

Time format is in normal Finnish time format. For example, 10.50 means 10:50.

Dates and times are in Finnish time, that is UTC+2/UTC+3. Remember to implement alternative_delivery_time and other fields that takes absolute date in correct timezone if the environment’s timezone does not match with the API’s.