Access Control System Integration

The following article explains how to integrate Cobot with access control systems such as smart door locks. The goal is to automatically give members access to various parts of your coworking space – depending on their membership level and various other factors.

Our integration will do two things:

  1. Synchronize Cobot member data to the access control system to give people access.
  2. Synchronize access data back to Cobot for attendance tracking.

For the purpose of this article, we will be integrating with a hypothetical smart lock system called … SmartLock.

SmartLock has its own cloud based management system and offers a simple JSON API that we will use for the integration. The API offers the following endpoints:

  • register user
  • a webhook when a user opens a lock

Authentication on SmartLock uses a fixed API token sent as an HTTP header called X-Api-Token.

We will be using various Cobot APIs. Most of all the subscription/webhook API, which allows us to get notified of events such as new members. We will also be using the check-in API for attendance tracking and the booking API to handle room bookings.

Cobot uses OAuth2 for Authentication.

We will be implementing different features in 5 steps, starting with the most simple one.

  1. Enable all active members of a space to access all locks.
  2. Check members in on Cobot when they access a lock (for attendance tracking, using up day passes).
  3. Only allow members access to some doors based on their membership level.
  4. Only give members access who have day passes.
  5. Give members access to a meeting room only when they have booked it.

We will implement our example integration using the Ruby programming language and Sinatra, a simple web framework. The source code should be relatively easy to read even if you don't know Ruby.

For this to work, we need to synchronize members to the SmartLock system when they start, and remove them again when they cancel.

Before we can start, we need access to both APIs – Cobot and SmartLock. We already have the API token for SmartLock. To get an OAuth token for Cobot, we need to implement one of the OAuth flows — or just create a client and copy/paste a token to get started.

First we store our access tokens in constants:

COBOT_ACCESST_TOKEN = "cobot-token-1"
SMARTLOCK_API_TOKEN = "sl-token-123"

In order get notified when a new member is added to our Cobot space, we are going to create a webhook for the membership_confirmed event using the Cobot subscription API.

Here’s the call to create a subscription for our Cobot test space (it lives under the subdomain "test-space"). We are using the rest-client library/gem to make HTTP requests.

RestClient.post "https://test-space.cobot.me/api/subscriptions",
  {
    event: "confirmed_membership",
    callback_url: "https://cobot-smartlock-integration.com/membership_confirmation"
  },
  {
    'Authorization': "Bearer #{COBOT_ACCESST_TOKEN}"
  }

We subscribe to the confirmed_membership event and pass the matching endpoint of our integration, to be called whenever a new member is confirmed on Cobot.

Here’s our webhook handler:

require 'sinatra'

post "/membership_confirmation" do
  # the webhook passes a url param that points to the newly confirmed membership
  membership = RestClient.get(params['url'])
  if membership['email']
    RestClient.post( # register user on SmartLock
      'https://api.smartlock.com/users',
      {email: membership['email]},
      {'X-Api-Token': SMARTLOCK_API_TOKEN}
    )
  end
end

Whenever a new membership on Cobot is confirmed, the endpoint sends a user registration request to SmartLock. We assume that SmartLock will handle things from here, for example send an invite to download an app, notify admins to prepare a key fob etc. Any permissions can be configured on the SmartLock website.

Thre is a membership_cancellation_date_reached webhook that we can subscribe to. When the event fires, the corresponding SmartLock user is deactivated.

Cobot offers a check-in mechanism which opens the door (sic) for two features:

  • Attendance tracking allows admins on Cobot to see which members were in the space on which day, but also statistics about attendance (for example per membership level).
  • Using up time passes: Cobot uses time passes to model memberships with limited access. Members are assigned a fixed number of passes, and once they have run out, should not be able to access the space anymore.

In order to enable check-ins, we need the SmartLock API to provide a webhook for when a member opens a lock. In addition, we need to map SmartLock users to Cobot memberships.

To create a mapping, let’s extend our user registration endpoint (we are leaving out the API headers to make the code more readable):

post "/membership_confirmation" do
  membership = RestClient.get(params['url']) # the webhook passes a url param that points to the newly confirmed membership
  if membership['email']
    response = RestClient.post(
      'https://api.smartlock.com/users', {
      email: membership['email']
      }
    )
    user_id = JSON.parse(response)['id']
    RestClient.post(
      "https://test-space.cobot.me/api/check_in_tokens",
      {
        membership_id: membership['id'],
        token: user_id
      }
    )
  end
end

Here we register the user_id that we got back from the SmartLock API as a so-called check-in token on Cobot. These tokens can later be used to check a member in without knowing their id or another identifier.

Now all we need to do is add a handler for the lock-opened webhook that we receive from SmartLock:

  # assumed webhook payload:
  # event: {"user": {"id": "the-user-id", ...}, ...}
  post "/lock_open" do
    user_id = JSON.parse(params['event'])['user']['id']
    RestClient.post(
      "https://tests-space.cobot.me/api/check_ins",
      {"token": user_id}
    )
  end

When receiving a lock-open event from SmartLock, we pull the user id from the payload and check the member in on Cobot. This will use up a time pass if applicable and generate the relevent statistics on Cobot.

There are multiple ways to achive this. Most access control systems have some concept of access groups, where all members of a group have access to a set of locks.

We can map the plans - which can be thought of as the membership level - in Cobot to those access groups.

We can do that either by name (beware: the name can be customized when a plan is assigned to a membership) or go by the ids of plans. Note: when a plan on Cobot is assigned to a membership, use the parent_plan.id of the membership's plan to compare it to the id of a plan of a space.

Another way would be to use Cobot's custom fields API. We could create a custom field that contains the ids or names of certain access groups or locks.

Memberships on Cobot can have limited access. This is controlled via time passes. Memberships whose plan has no time passes are unlimited.

If the plan has time passes, the member should only have access as long as they have time passes and only at the time the passes are valid (see parsed_timespans in the time passes API).

In order to keep our access control integration informed about time passes, we need to subscribe to the following webhooks:

  • membership_removed_time_passes - removing time passes could lead to the count to go to zero, hence the member's access needs to be suspended
  • membership_added_time_passes - when this is triggered, a member could go from 0 to more time passes and access needs to be restored
  • created_checkin - checking in uses up time passes, so they could run out again and access would need to be suspended

To check how many time passes a member has left, call the membership time passes endpoint.

Members in a space can typically book meeting rooms. On Cobot, these are called resources.

If a room with a lock is booked by a member, they should be granted access to the room's lock (plus any locks they need to get to the room) for the duration of their booking (plus a few minutes of buffer time).

For that purpose, Cobot provides the booking_will_begin and booking_has_ended webhooks.

To fetch a booking's details such as the resource it belongs to, there is the booking AP.

On the access control side, a temporary access control group can be created when the bookng starts, and deleted again when it is over.

Cobot has a feature where non-members ("visitors") can book a resource.

When an external booking is made, a "normal" booking is made as well, so the webhooks under "Give members access to meeting rooms" can be used.

The bookings will not have a membership_id, but an externalBooking relationship on Cobot's API2.

The external booking has an email and a phone number, which can be used to invite the visitor to the access control system.

back to index