Introduction

Welcome to the documentation and reference page of the EVVA AirKey Cloud API. Our REST API provides the customer with powerful control of his AirKey infrastructure from any third-party application.

Features

These features can be controlled via API:

  • Manage persons
  • Manage smartphones and other access media like cards, key tags, etc.
  • Assign smartphones or other access media to persons
  • Authorize smartphones or other access media to access locks (locking components) or areas at given times
  • Access protocols
  • Additional administration for blacklists, credits, holiday calendars, and maintenance tasks

Some components of AirKey cannot be controlled through the API, as they have no internet connection. This concerns mostly parts which are set up only once:

  • Registering new locks and their assignment to areas
  • Adding new RFID access media like cards and key tags
  • Administrative settings as buying credits or requesting API keys

API Activation

You need to generate a secret API key to access the API. The key is sent through a HTTP header (X-API-Key) every time you access the API. Beside the production API, we provide a test environment for development purposes. Here you can try out all API features in a safe sandbox-like environment.

To activate the API open the AirKey Online Administration at https://airkey.evva.com in your web browser. Go through the "AirKey registration" process if you haven't registered yet. Then log in and choose "Settings".

Test API

The test environment is free of charge. A predefined set of test data can be loaded and reset to the intial state anytime.
Please note that it is not possible to access the test environment's data in the AirKey Online Administration. Furthermore no real SMS text messages will be sent in the test environment.

To activate the test API go to "Settings" → "AirKey Cloud Interface (API) – test environment" and select "Generate the API key". Immediately write down the API key, as it is displayed only once for security reasons.

You can reset the provided test data to the predefined data set anytime by clicking on "Reset test data" or by sending the "/v1/public-mgmt/reset-test-data" request via the API.

Production API

To activate the actual production API click the "Activate API" button (350 credits needed). After the activation you can generate your secret API key. The key is displayed only once. Use this key instead of the test API key to switch from testing to production operation.

Attention, you are now working with real production data!

In case of problems, please try to reproduce them in the test environment before contacting support.

Connecting to the API

There are several ways in which you can access the EVVA AirKey Cloud API:

Manually

The easiest way to perform requests is by using the built in "Try it out" feature of the Swagger Documentation below. First click on "Authorize" and enter your API key. Then you can use the "Try it out" button next to each request.

Another convenient option is to use a tool like Postman.

From your application

To access AirKey directly from your application you have two main options: You can simply send direct request with tools like "curl" and handle the requests yourself, or you can use generated classes for your programming language via the Swagger Generator.

Here is a short run-down of how to use Swagger Generator:

  • Go to https://generator.swagger.io
  • Click on "clients" → "POST /gen/clients/{language}"
  • Click on "Try it out"
  • Select the programming language of choice
  • Set the "body" field as follows:
    {
        "spec": {},
        "options": {},
        "swaggerUrl": "https://integration.api.airkey.evva.com/docs/swagger.json"
    }
    
  • Then click the blue "Execute" button
  • You can now download the generated lib at the URL given in the "Response body"

Please note that EVVA cannot provide any implementation support for the API. Contact your software development, agency or vendor for support.

How to use the API

In the following we provide some general information about the usage of the API:

Swagger Documentation

Below you can find the extensive Swagger Documentation for all request types and models (objects). Information about the request URLs, query parameters, request body configuration, examples of body and response, as well as valid response codes are provided there.

For body and response you can click on the "Model" link to get information about the fields. Provided are details about data type, required (marked by a red asterix) and read only. Note that you can expand child models by clicking on them.
Example: GET /v1/persons → Responses → Model → personList (click on the right angle bracket) → Person → correspondenceLanguageCode (click on the right angle bracket)

Authorization header "X-API-Key"

For each request a valid API key must be sent in the HTTP header (name "X-API-Key"). To generate a new API key, see section "API Activation".

Data format JSON

JSON notation is used throughout the API:

  • Responses are returned as JSON.
  • PUT and POST request bodies expect JSON.
  • DELETE requests take a JSON array of object IDs.

URL encoding

Make sure to properly apply URL encoding for query parameters according to RFC 3986.

Paging

Most GET requests use paging. Per default 20 entries are returned. You can retrieve up to 100 entries by giving the "limit" query parameter.

Example: /persons?limit=100

Subsequent pages are loaded via the "offset" query parameter (number of entries to be skipped at the beginning of the delivered list).

Example to load max. 10 entries beginning with 3rd entry (skip first 2 entries): /persons?limit=10&offset=2

Workflow of updating objects and versioning

If you want to update an existing object you should retrieve it first via GET request, modify the values as you wish, and then perform a PUT request.

The reason for that is that many PUT requests require to add the current version of the object. This is important to avoid concurrent modifications and overrides.

Please note that you have to give all required fields, even if they are read only.

Language and country codes

Currently supported:

  • 11 language codes (ISO 639-1 compliant and case sensitive):
    cs-CZ, de-DE, en-UK, es-ES, fr-FR, it-IT, nl-NL, pl-PL, pt-PT, sk-SK, sv-SE
  • 250 country codes (ISO 3166-1 alpha-3 compliant and case sensitive):
    ABW, AFG, AGO, AIA, ALA, ALB, AND, ANT, ARE, ARG, ARM, ASM, ATA, ATF, ATG, AUS, AUT, AZE, BDI, BEL, BEN, BES, BFA, BGD, BGR, BHR, BHS, BIH, BLM, BLR, BLZ, BMU, BOL, BRA, BRB, BRN, BTN, BVT, BWA, CAF, CAN, CCK, CHE, CHL, CHN, CIV, CMR, COD, COG, COK, COL, COM, CPV, CRI, CUB, CUW, CXR, CYM, CYP, CZE, DEU, DJI, DMA, DNK, DOM, DZA, ECU, EGY, ERI, ESH, ESP, EST, ETH, FIN, FJI, FLK, FRA, FRO, FSM, GAB, GBR, GEO, GGY, GHA, GIB, GIN, GLP, GMB, GNB, GNQ, GRC, GRD, GRL, GTM, GUF, GUM, GUY, HKG, HMD, HND, HRV, HTI, HUN, IDN, IMN, IND, IOT, IRL, IRN, IRQ, ISL, ISR, ITA, JAM, JEY, JOR, JPN, KAZ, KEN, KGZ, KHM, KIR, KNA, KOR, KWT, LAO, LBN, LBR, LBY, LCA, LIE, LKA, LSO, LTU, LUX, LVA, MAC, MAF, MAR, MCO, MDA, MDG, MDV, MEX, MHL, MKD, MLI, MLT, MMR, MNE, MNG, MNP, MOZ, MRT, MSR, MTQ, MUS, MWI, MYS, MYT, NAM, NCL, NER, NFK, NGA, NIC, NIU, NLD, NOR, NPL, NRU, NZL, OMN, PAK, PAN, PCN, PER, PHL, PLW, PNG, POL, PRI, PRK, PRT, PRY, PSE, PYF, QAT, REU, ROU, RUS, RWA, SAU, SCG, SDN, SEN, SGP, SGS, SHN, SJM, SLB, SLE, SLV, SMR, SOM, SPM, SRB, STP, SUR, SVK, SVN, SWE, SWZ, SXM, SYC, SYR, TCA, TCD, TGO, THA, TJK, TKL, TKM, TLS, TON, TTO, TUN, TUR, TUV, TWN, TZA, UGA, UKR, UMI, URY, USA, UZB, VAT, VCT, VEN, VGB, VIR, VNM, VUT, WLF, WSM, YEM, ZAF, ZMB, ZWE

Dates and times

Timestamps are generally provided in ISO 8601 date and time format, with time in UTC and millisecond precision. The UTC timezone is defined by the letter "Z" (for zero meridian) in the last position. Seconds and milliseconds are optionally.

Example: 2019-05-09T09:25:36.608Z

Date fields which hold only the date without time follow a naming convention with "Date" suffix.
Example: "validFrom" (date + time) vs. "validFromDate" (only date)

Dates and times for authorizations

Attention: Timestamps for authorizations are given without timezone (without letter "Z" in the last position), because locks work in the local timezone and need times relative to their time zone. For example you want to provide access to a door at 4:00 p.m. in the time zone of the lock, and not at 4:00 p.m. UTC.

Example: 2019-05-09T09:30    /* without letter "Z" in the last position */

Furthermore authorization timestamps take only certain minute values and no seconds or milliseconds.
Valid minute values for authorization: 00, 05, 10, 15, 20, 30, 40, 45, 50, 55

ID vs. Identifier

The API uses the following naming convention regarding IDs:

  • ...Id is the native database ID (e.g. lockId=140023087)
    Most of the time you will use these native database IDs when working with the API.
  • ...Identifier is the component identifier used in the AirKey Online Administration for access media and locks (e.g. lockIdentifier=000000000858E6D0)

HTML code formatting for protocol entries

The translation fields for protocol responses contain various CSS class definitions. The necessary files for human friendly representation for these fields are:

Workflow Example: Authorization

In this section we give you a short introduction of a common authorization life cycle.
You can also try out and inspect these requests in our API Demo App.

Create authorization for smartphone

The simplest way to create an authorization for a smartphone is to use the convenient "/send-a-key" request. This is a single simplified interface for multiple requests in the background: create a person, create a "phone" medium, assign the medium to the person and create an authorization for the phone to the given lock (or area) and time.

Update

To update data from the previous "/send-a-key" request you need to perform separate update requests for the involved data models:

  • To modify personal data (firstName, ...) you need to "GET" the person via "/v1/persons/{personId}" and then "PUT" the modified JSON object.
  • To modify data of the medium (mobileNumber, ...) you need to "GET" the medium via "/v1/media/{mediaId}" and then "PUT" the modified JSON object.
  • Authorizations are very powerful in AirKey and thus a bit more complex.
    If you simply want to replace all existing authorizations created by "send-a-key" you can do the following:
    POST /v1/authorizations/simple
    {
         "authorizationInfo": {
             "type": "SIMPLE",
             "validFrom": "2019-05-15T09:50",
             "validTo": "2019-06-21T09:00"
         },
         "mediumId": 253,
         "lockId": 140023087,
         "removeAllExistingAuthorizationsForPair": true
    }
    

    Explanation: We logically create an authorization of type "SIMPLE" which takes only "validFrom" and "validTo" timestamps, and the IDs of medium and lock. Afterwards it is checked against all existing authorizations.

    Additionally we give the option "removeAllExistingAuthorizationsForPair" in case of a necessary authorization change, applying on the current medium–lock pair. Meaning:

    • If "removeAllExistingAuthorizationsForPair" is set to "true" the logically created authorization will replace all existing authorizations.
    • If "removeAllExistingAuthorizationsForPair" is set to "false" (= default value) the logically created authorization will be appended to the existing authorizations, if technically possible. Overlapping intervals are not allowed; exception: the new time interval covers exactely an existing time interval. For one day you can create only one time interval with the SIMPLE authorization (e.g. only 09:00-10:00, but not 09:00-10:00 and 14:00-16:00).

    This request is also possible for an area. Use in this case "areaId" instead of "lockId".

Delete

If you want to delete all data created by a "/send-a-key" request you have to perform the following steps in the correct order:

  • POST /v1/media/{mediumId}/empty
    Removes all authorizations from a medium.
  • POST /v1/media/cancel-assignment
    Takes the {mediumId} as body and unassigns the medium from the person.
  • DELETE /v1/media/phones
    Takes {mediumId} as body and removes the phone entry.
  • DELETE /v1/persons
    Takes {personId} as body and removes the person entry.

Additional Information

A lot of additional information can be found in the AirKey System Manual.

Please contact your EVVA partner for AirKey support inqueries.

Changelog

v17.20.0

  • Modified model LockDoor: name = door name set by owner of the lock (previously door name or alternative door name), ownerName removed, alternativeName added (alternative door name that can be set for locks with ownerShip = EXTERNAL, never used for locks with ownerShip = OWNER)
  • Modified model SimpleLock: alternativeName added (alternative door name that can be set for locks with ownerShip = EXTERNAL, never used for locks with ownerShip = OWNER). New field may only be returned by "GET /v1/maintenance-tasks".
  • Modified model SharedLock: renamed doorName to alternativeDoorName
  • Modified "GET /v1/maintenance-tasks": added query parameter alternativeDoorName to filter by alternative door name. Changed query parameter doorName to only filter by door name (previously also filtered by alternative door name).

v17.10.0

  • Replaced boolean field "synchronizeAfterUnlocking" in model LockSettings with "unlockSyncMode" of type LockUnlockSyncMode.

v17.0.0

  • Added optional fields "ownership" and "removalRequested" (both read-only) to the model Lock.
  • Added optional field "ownership" (read-only) to the model LockSettings.
  • Added GET and PUT request "/v1/locks/{lockId}/settings" which allows fetching and modifying the settings of a lock. Some settings can only be changed by the owner of the lock and some may also needs lock synchronization to take effect.
  • Added requests "GET /v1/locks/{lockId}/settings/assigned-areas", "POST /v1/locks/{lockId}/settings/assigned-areas/add" and "POST /v1/locks/{lockId}/settings/assigned-areas/remove" for assigning / unassigning a lock to areas.
  • Added requests "GET /v1/locks/{lockId}/settings/sharing-codes", "POST /v1/locks/{lockId}/settings/sharing-codes" and "DELETE /v1/locks/{lockId}/settings/sharing-codes/{sharingCodeId}" for adding / removing sharing codes which allow the lock to be shared with another access control system. These requests can only be used by the owner of the lock.
  • Added requests "GET /v1/locks/{lockId}/settings/active-shares" and "POST /v1/locks/{lockId}/settings/active-shares/remove" for seeing with whom the lock is shared and to cancel shares with another access control systems. These requests can only be used by the owner of the lock.
  • Added request "POST /v1/locks/add-shared-lock" which allows adding a lock of another access control system.
  • Added requests "POST /v1/locks/{lockId}/remove" and "POST /v1/locks/{lockId}/abort-remove" for marking / unmarking a lock as to be removed. The lock needs to be synchronized to complete the removal. These requests can only be used by the owner of the lock.

v16.20.2

  • Added POST request "/v1/media/phones/{phoneId}/send-registration-code-with-parameters" which allows to send a registration code to a phone with an optional field (JSON body with field "smsText") to define the SMS text that should be used. If the field "smsText" is not set, a default text will be used.
  • Added optional field "cardUid" to the model Card which returns the ISO/IEC 14443 UID. GET requests /v1/media/... are going to return this field for supported media (J80K+D08K or newer) of type Card. This field is read-only and therefore cannot be updated. The "cardUid" can be returned only for cards produced after 13 September 2022!
  • Added required field "lockingSystemId" to the model Medium. GET requests /v1/media/... are going to return this field for media of all types. This field is read-only and therefore cannot be updated. Furthermore, media can now be filtered by using the new query parameter "lockingSystemId" (GET requests /v1/media, /v1/media/cards, /v1/media/phones).
  • Added required field "lockingSystemId" to the model Lock. GET requests /v1/locks/... are going to return this field for all locks. This field is read-only and therefore cannot be updated. Furthermore, locks can now be filtered by using the new query parameter "lockingSystemId" (GET request /v1/locks).
  • "GET /v1/maintenance-tasks" can now return the new maintenance task "RS485_OUTPUT_NOT_SYNCHRONIZED" (within model LockMaintenanceTask).
  • Added optional field "pushMessage" to the models AuthorizationChange and SimpleAuthorizationCreate. If this field is set, it will be shown on the phone that receives a new / changed authorization. Otherwise, the default push message text is used.

v15.10.0

  • Updated documentation for constraints of "POST /v1/media/{mediumId}/deactivate" and /v1/media/{mediumId}/reactivate (reason, comment query parameters)

v14.40.2

  • The requests "POST /v1/send-a-key" and "POST /v1/authorizations/simple" now only use the parameter "removeAllExistingAuthorizationsForPair". The parameter "allowModificationExistingAuthorizations" was removed.

v13.30.1

  • Fixes issue of finding phones via "GET /v1/media/phones" using the "phoneNumber" filter if the phone number contains blank characters.
  • Improved description for authorization update using "simpleAuthorization" in documentation.

v13.20.11

  • The request "PUT /v1/locks" now also saves the comment field.
  • Improved description for "simpleAuthorization" in documentation.
  • Renamed authorization date fields (without time) to "validFromDate" and "validToDate" for the types "ONE_DAY" and "PERIODICAL".
  • Added fields "fax" and "contactTitle" to the "GET /v1/customer" request.
  • Removed redundant requests "GET /v1/areas/protocol" and "GET /v1/locks/protocol". These requests are now handled by the "GET /v1/lock-protocol" request with a corresponding parameter ("areaId" respectively "lockId").
  • All requests use now the plural of "slot": "GET /v1/holidayCalendars/.../slots/", etc.