NAV Navbar
Logo
shell python

Introduction

This is the documentation for the HTTP API provided by KIWI.KI GmbH for remote unlocking and administration of doors. This API can be used for integration into existing systems and for application development.

You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs on the top right.

Pre-release Disclaimer

Stable releases of the KIWI API are forthcoming.

Getting Started

Getting a User Account

A user account is required for most interactions with the KIWI API. An account can be obtained by:

See KIWI Applications to learn more about apps available for user account administration.

Getting Permissions to a Door

A user account must be granted permissions to a door before that user can unlock it remotely or perform other actions with it using the API. Permissions can be granted by an administrator or manager using Portal.

See Permissions for more information.

Getting a session key

curl https://api.kiwi.ki/pre/session/ -d '{"username":"[email protected]", "password":"mypassword"}' -H 'Content-Type: application/json'

Reponse:

{
  "status": "ok", 
  "result": {
    "session": {
      "username": "[email protected]", 
      "max_expires": "2017-04-03T14:45:32.954709+02:00", 
      "expires": "2017-01-11T14:45:32.954709+01:00", 
      "enabled": "2017-01-03T14:45:32.841411+01:00", 
      "organization_id": 42, 
      "user_id": 1234, 
      "session_key": "cda9341330b0bab64b713a866b24b477", 
      "account_verification": 11
    }, 
    "session_key": "cda9341330b0bab64b713a866b24b477"
  }
}

A valid session key is a required parameter for most API requests. With a user account, a session key can be retrieved using the /pre/session/ endpoint:

Perform a POST to https://api.kiwi.ki/pre/session/ with the payload in the form:

{"username": "[email protected]", "password": "my_password"}

Example session key: cda9341330b0bab64b713a866b24b477

See Authentication for more information.

Opening a door

curl -X POST "https://api.kiwi.ki/pre/sensors/123/act/open/?session_key=cda9341330b0bab64b713a866b24b477"

Reponse:

{
  "status": "ok"
}

Each KIWI equipped door has an associated sensor, which can detect KIWI Kis and trigger unlocking of the door.

Perform a POST to https://api.kiwi.ki/pre/sensors/<sensor_id>/act/open/?session_key=<session_key> to unlock a door.

Where sensor_id is the ID of the sensor connected to the door, and session_key corresponds to a valid session obtained earlier with a username/password. See Open Door for more information.

See Sensors for how search and retrieve sensor IDs.

API Requests

Base URL

The base URL for making HTTP requests with the KIWI API is

Where /pre/ indicates Pre-release status.

HTTPS is required for all API requests.

Parameters

When making HTTP requests with the KIWI API, parameters can be passed in two ways:

Query String

For GET requests, a query string must be used.

A query string can be appended to the request URL with the parameter names and values. E.g.

In this example the session_key parameter is passed with the value “94be2d729ed71bf7d5860404e6d500e1” to the sensors endpoint.

Request Body

For POST requests, parameters must be passed in the request body with the content type application/json.

cURL example:

Where the -d flag specifies the body, and -H specifies the request headers.

Authentication

Before most API requests can be made, a login session must be started by providing a valid username and password. A session key will then be given back from the API, which can be used for authentication on further API requests.

Authentication with a session key covers general access to the API endpoints, but for controlling individual permissions to doors, see Permissions.

Get Session Key

curl https://api.kiwi.ki/pre/session/ -d '{"username":"[email protected]", "password":"mypassword"}' -H 'Content-Type: application/json'
import requests

login_credentials = dict(
    username="myusername",
    password="supersecretpassword")

response = requests.post(
    "https://api.kiwi.ki/pre/session/",
    json=login_credentials)

print(response.json())  

Reponse:

{
  "status": "ok", 
  "result": {
    "session": {
      "username": "myusername", 
      "max_expires": "2017-03-12T17:12:52.727104+01:00", 
      "expires": "2016-12-12T18:12:52.727104+01:00", 
      "enabled": "2016-12-12T17:12:52.613417+01:00", 
      "is_admin": false, 
      "user_id": 25, 
      "session_key": "5633238d67040b7316456e47ec5181e0", 
      "account_verification": 1
    },
    "session_key": "5633238d67040b7316456e47ec5181e0"
  }
}

HTTP Request

POST /pre/session/

Query Parameters

Name Type Description Example
username string (required) The username for the user account, which is usually an email address. [email protected]
password string (required) The password for the user account.

Response

Field Type Description
username string The username of the authenticated user (usually an email address).
max_expires datetime The maximum lifetime of the session in timezone aware ISO 8601 format.
expires datetime The expiration time while inactive in timezone aware ISO 8601 format.
enabled datetime The creation time of the session in timezone aware ISO 8601 format.
is_admin boolean True only for KIWI staff with admin rights.
user_id integer The user’s unique identifier.
session_key string All further API requests that require authentication will need this value to be passed as session_key.
account_verification integer Your verification level.

Verification Level

Level Description
0 Uncompleted online registration.
1 Unverified account.
2 Unverified account with claimed Ki.
11 Verified online user account.
12 Verified offline (managed) user account.

The result.session_key is deprecated and should not be used. Use result.session.session_key instead.

For more information about obtaining a user account, see this getting started section.

Permissions

For each sensor (door), permissions on that sensor control:

Permission Type Able to Grant Description
Guest (None) The user is able to unlock the door, but cannot grant any other user permission to the door.
Host Guest The user is able to unlock the door, and can grant other users Guest permission to the door (but no other permission type).
Manager Host, Guest The user is able to unlock the door, and can grant other users Guest or Host permission to the door.
Admin Manager, Host, Guest The user is able to unlock the door, and can grant other users Guest, Host or Manager permission to the door.

Addresses

curl https://api.kiwi.ki/pre/addresses/search/\?street\=Voltastr.\&number\=5\&plz\=13355

Reponse:

{
  "status": "ok", 
  "result": {
    "total_results": 0, 
    "results": [], 
    "exists": true
  }
}

With this special endpoint, you can check if an address exists in our system. An existing address indicates that this building is already KIWI equipped.

the value "exists": true tells you that a door sensor is available at this address.

Non-authenticated users are permitted to know the existence of sensors ("exists": true) but may not be permitted to see details about those sensors. In this case an empty results list is returned.

GET /pre/addresses/search/

Parameter Type Description Example
street string Street name in Deutsche Post Data Factory Format Voltastr.
number integer House or apartment number 5
plz integer ZIP code 13355

Sensors

List Sensors

curl https://api.kiwi.ki/pre/sensors/?session_key=94be2d729ed71bf7d5860404e6d500e1

In some cases, you want to search for an Address but you don’t know the exact address format. Use the fuzzy search field combined with filters.

curl https://api.kiwi.ki/pre/sensors/\
  ?session_key=d89eed49cdb851431eacbff8d948927f\
  &page_number=1&page_size=20\
  &search=Volta\
  &postal_code=13355\
  &city=Berlin
import requests

doorlist_params = dict(
    session_key="d89eed49cdb851431eacbff8d948927f",
    page_number=1,
    page_size=20,
    search="Volta",
    postal_code=13355,
    city="Berlin",
)

response = requests.get(
   "https://api.kiwi.ki/pre/sensors/",
   params=doorlist_params
)

print(response.json())

Reponse:

{
  "status": "ok", 
  "result": {
    "order_by": "ASC", 
    "total_results": 1, 
    "page_size": 20, 
    "sort_by": "id", 
    "page_number": 1, 
    "sensors": [
      {
        "hardware_type": "DOOR", 
        "sensor_id": 9403, 
        "highest_permission": null, 
        "image": null, 
        "hardware": "3A", 
        "device_type": "PUBLIC", 
        "address": {
          "city": "Berlin", 
          "specifier": "Tofus Apartment", 
          "country": "DE", 
          "state": "Berlin", 
          "street": "Voltastr. 11", 
          "postal_code": "13355", 
          "lat": 52.54189825, 
          "lng": 13.39018362, 
          "id": 4731
        }, 
        "sensor_uuid": "PewYGAAAMFO9gHlQAQAA9Q==", 
        "sensor_name": null, 
        "is_owner": false, 
        "firmware": "11110e", 
        "crystal": null, 
        "can_invite": false
      }
    ]
  }
} 

Returns a list of sensors (doors) that the authenticated user has access to.

HTTP Request

GET /pre/sensors/

Parameters - Authentication

Name Type Description Example
session_key string (required) A valid API session key. See Authentication. 5633238d67040b7316456e47ec5181e0

Parameters - Pagination / Sorting

Name Type Description Example
sort_by string (optional) Property to sort results by. (‘id’, 'distance’, 'specifier’, 'street’, or 'postal_code’) street
order_by string (optional) Sorting direction ('asc’ or 'desc’) desc
page_size integer (optional) The number of sensors to return. 20
page_number integer (optional) When page_size is given, specifies the page index. 5

Parameters - Filtering

Name Type Description Example
search string (optional) Only include sensors that have a partial case-insensitive match to the given string for the 'specifier’, 'street’, 'postal_code’ or 'city’ properties. Voltastr. 5 Berlin
specifier string (optional) Only include sensors that have a case-insensitive match to the given string for the 'specifier’ property. Keller
street string (optional) Only include sensors that have a case-insensitive match to the given string for the 'street’ property. Voltastr. 5
city string (optional) Only include sensors that have a case-insensitive match to the given string for the 'city’ property. Berlin
state string (optional) Only include sensors that have a case-insensitive match to the given string for the 'state’ property. Niedersachsen
postal_code string (optional) Only include sensors with the given postal code. 13355
device_type string (optional) Only include sensors of the given type ('PUBLIC’, 'PRIVATE’, 'TEST’). TEST
permission string (optional) Only include sensors for which the authenticated user’s permission type to the sensor is equal or greater than the given type. Possible values: 'IS_GUEST’, 'IS_HOST’, 'IS_MANAGER’, 'IS_ADMIN’. IS_HOST
firmware string (optional) Only include sensors with the given firmware version.
hardware string (optional) Only include sensors with the given hardware version.
crystal string (optional) Only include sensors with the given crystal type.

Parameters - Geolocation

Name Type Description Example
lat float (optional) Latitude. When lat and lng are specified, the list of sensors returned will be sorted by their proximity to the given geolocation. 52.508125
lng float (optional) Longitude. When lat and lng are specified, the list of sensors returned will be sorted by their proximity to the given geolocation. 13.460401
max_distance float (optional) When lat and lng are specified, only sensors that are within the given distance (in kilometers) will be returned. 0.5

Get Sensor Details

curl https://api.kiwi.ki/pre/sensors/9403/?session_key=94be2d729ed71bf7d5860404e6d500e1
import requests

# use our example door
sensor_id = 9403
session_key = "94be2d729ed71bf7d5860404e6d500e1"

response = request.get(
    "https://api.kiwi.ki/pre/sensors/%s/" % sensor_id,
    params={"session_key":session_key}
)

print(response.json())
{
  "status": "ok",
  "result": {
    "sensor": {
      "hardware_type": "DOOR",
      "sensor_id": 9403,
      "highest_permission": null,
      "image": null,
      "hardware": "3A",
      "device_type": "PUBLIC",
      "address": {
        "city": "Berlin",
        "specifier": "Tofus Apartment",
        "country": "DE",
        "state": "Berlin",
        "street": "Voltastr. 5",
        "postal_code": "13355",
        "lat": 52.54189825,
        "lng": 13.39018362,
        "id": 4731
      },
      "sensor_uuid": "PewYGAAAMFO9gHlQAQAA9Q==",
      "sensor_name": null,
      "is_owner": false,
      "firmware": "11110e",
      "crystal": null,
      "last_configuration": {
        "pushed": "2016-11-29T17:07:25.360179+01:00",
        "updated": "2016-11-29T17:06:21.772560+01:00",
        "result": "Command conf failed: retry limit exceeded",
        "success": false
      },
      "can_invite": false
    }
  }

HTTP Request

GET /pre/sensors/<sensor_id>/

Parameters

Name Type Description Example
session_key string (required) A valid API session key. See Authentication. 5633238d67040b7316456e47ec5181e0
sensor_id integer (required) The unique ID of the sensor. 9403

Open Door

curl -X POST https://api.kiwi.ki/pre/sensors/9403/act/open/?session_key=94be2d729ed71bf7d5860404e6d500e1
import requests

# assuming you already have a session_key
session_key = "94be2d729ed71bf7d5860404e6d500e1"
sensor_id = 9403

resonse = requests.post(
    "https://api.kiwi.ki/pre/sensors/%s/act/open?session_key=%s" % (sensor_id, session_key)
)

print(response.json())
{
  "status": "ok"
}

Given authentication and sufficient permissions, allows unlocking of a door connected to a sensor.

HTTP Request

POST /pre/sensors/<sensor_id>/act/open

Parameters

Name Type Description Example
session_key string (required) A valid API session key. See Authentication. 5633238d67040b7316456e47ec5181e0
sensor_id integer (required) The unique ID of the sensor. 9403

Assign Custom Name to Sensor

curl 'https://api.kiwi.ki/pre/fnames/sensor/9403/' \
-H 'Content-Type: application/json; charset=UTF-8' \
-d '{"session_key":"94be2d729ed71bf7d5860404e6d500e1","friendly_name":"foobar"}'
import requests

session_key = "94be2d729ed71bf7d5860404e6d500e1"
sensor_id = 9403

name_parameter = {
    "friendly_name": "foobar"
}

response = requests.post(
    "https://api.kiwi.ki/pre/fnames/sensor/%s/?session_key=%s" % (sensor_id, session_key),
    data=name_parameter
)

print(response.json())

{
  "status": "ok",
  "result": {
    "sensor_id": "9403",
    "fname": "My Red Door"
  }
}

Assigns a custom name to a sensor. Each user may assign their own names to each sensor; these custom names are visible only to the users that created them.

Custom names will appear in the sensor_name fields returned by the /sensors and /sensors/<sensor_id> endpoints.

POST /pre/fnames/sensor/<sensor_id>/

Parameters

Name Type Description Example
session_key string (required) A valid API session key. See Authentication. 5633238d67040b7316456e47ec5181e0
sensor_id integer (required) The unique ID of the sensor. 9403
fname string (required) A custom name to give to the sensor. My Red Door

Users

Get User Details

curl https://api.kiwi.ki/pre/users/2664/?session_key=178d3d01a1872f58573183833897a732

Reponse:

{
  "status": "ok",
  "result": {
    "user": {
      "username": "[email protected]",
      "friendly_name": null,
      "contact": {
        "name": "Foo",
        "segment_id": "10",
        "lastname": "Barrington",
        "title": "Mr",
        "customer_number": "10DE1600002664",
        "country": "DE"
      },
      "user_id": 2664,
      "organization_id": 61
    }
  }
}

GET /pre/users/<user_id>/

Parameters

Name Type Description Example
session_key string (required) A valid API session key. See Authentication. 5633238d67040b7316456e47ec5181e0
user_id integer (required) The unique ID for the user. Note that the session endpoint returns the user_id. 123

Create a new User

curl -X POST -d \
'{
    session_key":"178d3d01a1872f58573183833897a732",
    "name":"Foo",
    "lastname":"Barrington",
    "title":"Mr",
    "segment_id":"10",
    "country":"DE",
    "i_have_read_and_accepted_kiwidotki_agb":true,
    "lang":"en",
    "password":"supersecretpassword",
    "email":"[email protected]"
}' https://api.kiwi.ki/pre/users/

Reponse:

{
    "status": "ok",
    "result": {
        "user": {
            "username": "[email protected]",
            "user_id": 2953,
            "email": "[email protected]",
            "myself_group_id": 21637
        }
    }
}

POST /pre/users/

Parameters

Name Type Description Example
session_key string (required) A valid API session key. See Authentication. 5633238d67040b7316456e47ec5181e0
email string (required) The email address of the new user. This will become the user’s username. [email protected]
password string (required) The new password for the user.
lang string (optional) The default language to use for correspondence and app display with this user. Defaults to ‘de’. en
country string (optional) The country of residence for the user. DE
segment_id string (optional) Marks which customer segment the user belongs to. 10

Terms and Conditions (AGB)

The KIWI.KI AGBs must be accepted for user account creation. The following parameter is mandatory:

Name Type Description Example
i_have_read_and_accepted_kiwidotki_agb boolean (required) 'true’ must be given, or the account creation request will be rejected. true

The user is now created in the system, but not verified yet. To use it, you need to verify the email address. For that, click on the verification link you just received via email.

Errors

The KIWI.KI API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request is buggy. Check the parameters
401 Unauthorized – Your are not logged in. Authenticate please.
403 Forbidden – The endpoint you requested is for administrators only
404 Not Found – The specified resource could not be found
405 Method Not Allowed – You tried to access a resource with an invalid method
406 Not Acceptable – You requested a format that isn’t json
410 Gone – The resource requested has been removed from our servers
418 I’m a teapot
429 Too Many Requests – Rate of requests exceeded limit.
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarially offline for maintenance. Please try again later.