With some smart home platforms or devices, LOQED has no direct integration. If you are an advanced user, you can develop your integration by using the LOQED API. Be sure to read our article "Advanced users: Available APIs" first.

When the door is opened/locked, call a URL (outgoing webhook)

When the lock’s status changes (open, unlock, lock) and for other information (battery percentage, online status), the LOQED Bridge can call (POST data to) a URL. Below you can find which data is POSTed as JSON to this URL. You can also add URL's GET parameters by setting the JSON key between "[" and "]". For example: https://your.server.nl/script?yourstate=[requested_state]. You can also choose for which changes a webhook call should be triggered (e.g., you can choose to only call a URL when the door is locked).

The following JSON keys are always sent:

  • mac_wifi: contains the Wi-Fi MAC address of the bridge. This helps to identify the bridge. The multicast DNS name of the bridge contains this address as well.

  • mac_ble: contains the Bluetooth MAC address of the bridge.

Reached state

After the motor stopped running, the below JSON keys are sent for the triggers trigger_state_changed_open, trigger_state_changed_latch, trigger_state_changed_night_lock, trigger_state_changed_unknown:

  • requested_state

    • OPEN

    • DAY_LOCK

    • NIGHT_LOCK

    • UNKNOWN

  • event_type

    • STATE_CHANGED_OPEN (requested_state = OPEN)

    • STATE_CHANGED_LATCH (requested_state = DAY_LOCK)

    • STATE_CHANGED_NIGHT_LOCK (requested_state = NIGHT_LOCK)

    • STATE_CHANGED_UNKNOWN (requested_state = UNKNOWN)

    • MOTOR_STALL (requested_state = UNKNOWN)

    • STATE_CHANGED_OPEN_REMOTE (requested_state = OPEN)

    • STATE_CHANGED_LATCH_REMOTE (requested_state = DAY_LOCK)

    • STATE_CHANGED_NIGHT_LOCK_REMOTE (requested_state = NIGHT_LOCK)

    • GO_TO_STATE_TOUCH_TO_LOCK (requested_state = NIGHT_LOCK)

  • key_local_id (null if e.g. manual opening by knob or pressing button). This contains the KeyID that changed the lock's state.

Going to a state

When the lock is going to a new position (it might not reach the position if the batteries are almost empty, for example) the below JSON keys are sent for the triggers trigger_state_goto_open, trigger_state_goto_latch, trigger_state_goto_night_lock:

  • go_to_state

    • OPEN

    • DAY_LOCK

    • NIGHT_LOCK

  • event_type

    • GO_TO_STATE_INSTANTOPEN_OPEN (Touch to Open) (go_to_state = OPEN)

    • GO_TO_STATE_INSTANTOPEN_LATCH (Auto Unlock) (go_to_state = DAY_LOCK)

    • GO_TO_STATE_MANUAL_UNLOCK_BLE_OPEN (go_to_state = OPEN)

    • GO_TO_STATE_MANUAL_LOCK_BLE_LATCH (go_to_state = DAY_LOCK)

    • GO_TO_STATE_MANUAL_LOCK_BLE_NIGHT_LOCK (go_to__state = NIGHT_LOCK)

    • GO_TO_STATE_TWIST_ASSIST_OPEN (go_to_state = OPEN)

    • GO_TO_STATE_TWIST_ASSIST_LATCH (go_to_state = DAY_LOCK)

    • GO_TO_STATE_TWIST_ASSIST_LOCK (go_to_state = NIGHT_LOCK)

    • GO_TO_STATE_MANUAL_UNLOCK_VIA_OUTSIDE_MODULE_PIN (go_to_state = OPEN)

    • GO_TO_STATE_MANUAL_UNLOCK_VIA_OUTSIDE_MODULE_BUTTON (go_to_state = OPEN)

    • GO_TO_STATE_TOUCH_TO_LOCK (go_to_state = NIGHT_LOCK)

  • key_local_id (255 means unknown, e.g. manual opening by knob or pressing button)

Battery percentage

When the lock sends the current battery percentage (every few hours) the below JSON keys are sent for the trigger trigger_battery:

  • battery_type (0 = Alkaline, 1 = NiMH, 2 = Lithium (non-rechargable), 3 = unknown)

  • battery_percentage

Online status

When the lock loses the connection to the bridge, the below JSON keys are sent for the trigger trigger_online_status:

  • wifi_strength (currently in dB, soon this will change to a percentage)

  • ble_strength (currently in dB, soon this will change to a percentage. -1 means the lock is not connected)

Verify if the webhook request came from the LOQED Bridge

You might take sensitive actions if the door opens (e.g., turn on the lights, turn off the alarm, turn on the heater). Therefore you need to ensure that on the URL that you supplied, no other devices can trigger such actions. You can:

  • Ensure no other devices can call the URL by limiting the IP only to the LOQED Bridge's IP address. Also, ensure the bridge IP address does not change by fixating this in the DHCP service of your router.

  • Verify the hash signature sent in the headers of the webhook call. In the header, you find TIMESTAMP (8 bytes) and HASH (hex). You can calculate the hash yourself by doing sha256(BODY + TIMESTAMP + base64_decode(bridge_authentication_key). The bridge authentication key can be found on https://app.loqed.com/API-Config. The BODY is the unaltered body received with the request (with all the JSON code). Also do not forget to validate if the timestamp is within a few seconds from the actual time, to prevent replay attacks.

List, add, and delete a webhook on the bridge using our tool

The easiest way to list, add or delete webhooks is by using our Javascript tool:

  1. Login on https://app.loqed.com/API-Config

  2. Scroll to the heading "Outgoing Webhooks via LOQED Bridge"

  3. Click on the button "Add/Delete webhooks" next to the correct bridge. The tool will open, and your bridge IP address and authentication key are pre-filled.

List, add, and delete a webhook on the bridge using your code

If you want to make it easier for users of your product to connect it to LOQED, you can also use the bridge API to set up the webhooks. Below the API endpoints are described. You can look at the code of the above-mentioned Javascript tool if you are looking for an example. The LOQED Bridge can be found using mDNS in your application (try "DNS-sd -B _http._tcp" on Windows for example)

For all /webhooks webserver methods two headers are mandatory:

  • TIMESTAMP: contains the current timestamp

  • HASH – sha256 hash string

The hash calculation is specific for each type of request and described in the corresponding section. You need the bridge's authentication key to be able to calculate the hash. This key can be found after logging in at https://app.loqed.com/API-Config. There is no other way to retrieve this key.

List webhooks
GET: https://bridge-ip-address/webhooks
The HASH in the header needs to be formatted: SHA256(TIMESTAMP + LOCK_TOKEN), where TIMESTAMP is an 8 bytes number and LOCK_TOKEN is the base64 decoded (!) bridge's security key (the key on the webhooks.loqed.com page is in base64). The HASH should be in hex.

Returns JSON array with keys:

Returns HTTP codes:

  • Return HTTP 400 BAD REQUEST code and string with description in case headers are invalid or not found

  • Return HTTP 401 UNAUTHORIZED if authentication failed

Create webhook
POST: http://bridge-ip-address/webhooks
Body: JSON with keys:

The HASH in the header needs to be formatted: SHA256(URL + trigger_bitmap + TIMESTAMP + LOCK_TOKEN), URL is a string, trigger_bitmap 4 bytes, TIMESTAMP is an 8 bytes number, and LOCK_TOKEN is the base64 decoded (!) bridge's security key (the key on the webhooks.loqed.com page is in base64). The HASH should be in hex. The trigger_bitmap contains the triggers. For example, 0x000F (15 decimal) is 0000 0000 0000 1010 in binary, which means that the following triggers are enabled:

  • "trigger_state_changed_open":0

  • "trigger_state_changed_latch":1

  • "trigger_state_changed_night_lock":0

  • "trigger_state_changed_unknown":1

  • "trigger_state_goto_open":0

  • "trigger_state_goto_latch":0

  • "trigger_state_goto_night_lock":0

  • "trigger_battery":0

  • "trigger_online_status":0

We have also a small PHP snippet that shows how a webhook is created, you can download it here.

Returns:

  • HTTP 200 OK code and string with description in case of successful webhook creation

  • HTTP 400 BAD REQUEST code and string with description in case if JSON is not valid for webhook creation

  • HTTP 400 BAD REQUEST code and string with description in case headers are invalid or not found

  • HTTP 401 UNAUTHORIZED if authentication failed

  • HTTP 500 INTERNAL SERVER ERROR code and string with description in case if webhook with this URL already exists

  • HTTP 500 INTERNAL SERVER ERROR code and string with description in case if MAX number of webhooks reach

Delete webhook
DELETE: http://bridge-ip-address/webhooks/{webhookId}
The HASH in the header needs to be formatted: SHA256(id + TIMESTAMP + LOCK_TOKEN), ID is an 8 bytes number, TIMESTAMP is an 8 bytes number, and LOCK_TOKEN is the base64 decoded (!) bridge's security key (the key on the webhooks.loqed.com page is in base64). The HASH should be in hex.

Returns:

  • HTTP 200 OK code and string with description in case of successful webhook deletion

  • HTTP 400 BAD REQUEST code and string with description in case headers are invalid or not found

  • HTTP 401 UNAUTHORIZED if authentication failed

  • HTTP 404 NOT FOUND code and string with description in case if webhook with {webhookId} was not found

  • HTTP 500 INTERNAL SERVER ERROR code and string with description in case any error during deletion occurred

Testing

We recommend using Webhook.site if you want to verify that your smart lock/bridge is calling the Webhook URL. You will also be able to see the JSON data there.

Open/lock the door when something happens (incoming webhook)

If you want to control your lock from a third-party service or device, you can do this by way of an HTTPS GET call to your LOQED Bridge URL.

Creating an API Key

First, you need to create a new key on your LOQED Touch Smart Lock.

image

  • Click on "Add new API key".

image

  • Enter a name for easy identification. This can be anything you like.

  • If you have multiple locks, you can select the right lock in the dropdown menu right next to "Select Lock".

  • Click "Add API Key".

image


You have now created the API key.

Call the API

Currently, the API supports the following commands:

  • Open (lock opens, then returns to latch. Only supported on doors without a handle on the outside). An empty JSON object is returned.

  • Latch (unlocked). An empty JSON object is returned.

  • Night lock (locked). An empty JSON object is returned.

  • Status. ATTENTION: we recommend only requesting the status once per day, to keep the load on the bridge to a minimum. Instead of asking for the status, you should implement a webhook that calls your server, so you get an instant notification as soon as the lock state changes. It returns the following JSON keys:

    • mac_wifi (lock identification)

    • mac_bluetooth

    • lock_online (1 if the lock is online, otherwise 0)

    • battery_percentage (-1 if the lock is offline, otherwise 0 - 100)

    • battery_type (0 = Alkaline, 1 = NiMH, 2 = Lithium (non-rechargable), 3 = unknown)

    • bolt_state_numeric (0 = unknown, 1 = open, 2 = day_lock, 3 = night_lock)

    • bolt_state (unknown, open, day_lock, night_lock)

Let the LOQED bridge generate the digital signature

Commands to the smart lock need to be digitally signed. The easiest is to let the LOQED bridge generate this signature. Simply use the four provided URLs (open, latch, night lock, status) shown on webhooks.loqed.com. Note that the HTTP connection to the bridge is not secured, thus other people on your local network could potentially retrieve the encryption key. If you want to securely send commands, you need to generate the digital signature yourself.

Generate the digital signature yourself

At https://app.loqed.com/Bridge-API-example/ we provide example code (Javascript and PHP) that shows how the digital signature is created. You can only use this method if you can create your plugin for the smart home system you want to connect to. The data you need (IP, secret, KeyID) can be found at https://app.loqed.com/API-Config after clicking the "View / Edit" button next to the API Key.

Did this answer your question?