Receiving Workspace Updates Via Syncaroo

Table of Contents

Who's this integration guide for.

This integration guide is designed for the developers of booking, brokerage, aggregator and discovery platforms that would like to receiving automatic updates about their users’ workspaces, pricing and resource information.

Developers of property management systems should contact us for integration information.

The integration is broken down into steps and is designed to help drastically reduce integration time and development resources.

Before getting started.

We will need a few bits of information from you, in order to get you set up with access to the Syncaroo Developers portal.

{
    "siteUri": "https://yourapp.com", 						// The base URL for your app & API connections.
    "apiUri": "https://yourapp.com/api/", 					// The base URL for your API, defaults to `<site_url>/api/`
    "authUri": "https://yourapp.com/api/oauth/authorize", 	// Redirect for authorizing platform-to-platform OAUth
    "webhookPath": "/update/", 								// The URL to where update notification webhooks should be sent. Appended to `<api_url>`.
    "checkConnectionPath": "/check_connection/", 			// The URL where Syncaroo can confirm an authorized connection. Appended to `<api_url>`.
} 

We recommend that platforms leverage OAuth for the authorization and authentication of connections between your users’ accounts and their Syncaroo accounts.

For OAuth Connections we’ll also need to the following details:

{
    "yourClientId": "xyz1243", 								 // OAuth Client ID for Syncaroo-to-Your handshake.
    "yourClientSecret": "...", 								 // OAuth Client Secret for Syncaroo-to-You handshake.
    "authTokenUri": "https://yourapp.com/api/oauth/token",   // Where to POST authorized user `token` to after handshake.
} 

Getting started.

What follows is a step-by-step process for installing and testing a connection between your platform and the Syncaroo platform.

Connecting your users' accounts.

Let’s start with what your platform’s users will see and do during the onboarding flow. 

Here’s what the end-result should look and feel like for your customers/users. 

User initiates a connection between Syncaroo and your platform.

When adding your integrated platform and clicking ‘Add Integration’, they’ll be redirected to the <auth_url> address you’ve provided.

We’ll send the following data via GET variables:

{
    "connectionId": 99, 									// An identifier for the integration between your user's management system and your platform.
    "clientId": "xyz1243", 									// the <client_id> you provided to Syncaroo during setup.
    "redirectUri": "https://app.syncaroo.com/connection", 	// The URL to redirect the user to with required parameters appended as GET variables.
    "response_type": "code"
} 

What your user sees:

User authorizes the connection.

The user should then be presented with a confirmation that they’re authorizing a synced connection between Syncaroo and their account’s listings on your platform.

If the user is not currently logged in, they should be asked to login before being able to authorize their connection to Syncaroo.

Redirect the user to Syncaroo to confirm the connection.

The link to authorize the connection from your platform should point to the <redirectUri> value you received, appended with following GET variables:

{
    "connectionId": 99, 			// the <connectionId> value you received with the authorization request.
    "code": "one-time-auth-string", // a string that we can use to authorize this user's connection 
} 

The user will the be taken through onboarding to confirm their connection.

Syncaroo will request tokens.

As the user returns to the <redirectUri>, Syncaroo will use the <code> GET variable provided to fetch OAuth tokens for this user.

Syncaroo will send a POST request to <auth_token_url> provided, with following headers:

{
    "Content-Type": "application/x-www-form-urlencoded"
} 

And the following body:

{
    "clientId": "xyz1243", 			// The Client ID you provided before getting started.
    "clientSecret": "...", 			// The Client Secret you provided before getting started. 
    "code": "one-time-auth-string", 	// The `code` parameter returned.
    "grantType": "authorization_code"
} 

Should the Authorization Code be correct, Syncaroo expects the following response:

{
    "accessToken": "{{accessToken}}", 	// Access Tokens should be short-lived with expiry date provided below.
    "expires" : "2009-06-15T13:45:30", 	// When the accessToken provided expires in default datetime format in UTC timezone.
    "refreshToken": "{{refreshToken}}", // Refresh Tokens should be longer-lived so that they can be used as one-time tokens to get new Access Tokens
} 

Syncaroo then completes and confirms the initial setup.

To complete the initial setup, Syncaroo will send a GET request to <api_url>/<check_connection_path> with the following headers:

{
    "Authorization": "Bearer {{accessToken}}"
} 

And the following parameters:

{
    "connectionId": 99, // The unique connection identifier provided in the beginning of the authorization flow.
} 

Using the <connectionId> and <accessToken>, your platform can identify the user and any workspace listings/profiles attached to their account.

In order to ensure that workspaces and resources are synced correctly, Syncaroo expects the following header: 

{
    "Content-Type": "application/json; charset=UTF-8"
} 

And a response schema based on this structure:

{
  "connectionId": 99,  					// The connection identifier.
  "userId": "1",       					// The user identifier.
  "locations": {
    "1198": {
      "ID": "1198", 						// Your internal identifier for this location. Used to sync back workspace data using an ID you can recognize.
      "name": "Demo Workspace - London", 	// The workspace location's title.
      "status": "active", 					// Your internal status (can be 'draft', 'active', 'private', 'pending' or 'deleted')
      "resources": [ 						// Array of resource objects connected to this workspace.
      {
        "ID": "7843",                         // Resource identifier.
        "name": "Demo Meeting Room - London", // Resource title.
        "status": "active",                   // Resource status.
        "type": "meeting-room"                // Resource type.
      },
      {
        "ID": "7842",
        "name": "Demo Private Office - London",
        "status": "active",
        "type": "office"
      }
      ]
    },
    "7120": {
      "ID": "7120",
      "name": "Demo Workspace - NYC, USA",
      "status": "draft"
    },
    "8102": {
      "ID": "8102",
      "name": "Demo Workspace - Berlin",
      "status": "private"
    },
    "9587": {
      "ID": "9587",
      "name": "Deleted Workspace",
      "status": "deleted"
    }
  }
} 

Receiving updates from Syncaroo.

Once a connection is authorized, confirmed and completed as per the above instructions, Syncaroo will send out an initial set of notifications (aka webhooks) with the latest available data for matched workspaces, resources, and prices.

After the initial sync, each time a change is made in a workspace’s management system (that affects this data set), a new webhook will be sent for affected resources and/or locations.

Below are instructions on how to parse the two different types of webhooks Syncaroo sends our, the first for Data Sync notifications (ie changes to workspace data) and the latter for Status Sync notifications (ie changes to a workspace’s lockdown status).

Handling Data Sync change notifications.

The following webhook will fire for a Data Sync change to the url made up of the <site_url>/<webhook_path> variables provided during setup.

In the headers:

{
  "Authorization": "Bearer {{accessToken}}" // The access Token received from your platform
} 

In the body:

{
  "connectionId": 99, 					// Connection identifier.
  "webhookType": "data", 				// Kind of webhook, can be either 'data' for a Data Sync webhook or 'status' for a Status Sync webhook.
  "locationId": "1198", 			    // Your internal idenfier for the affected location.
  "metaData": {
    "resourceId": "19284",              // If webhook relates to a resource, your identifier will be returned here.
    "attributeType": "resources", 		// The attribute level receiving the update, options are 'locations' (workspace data), 'resources' (bookable resources), or 'rates' (pricing). 
    "resourceType": "meeting-room" 		// If attributeType is 'resource', this value will discribe the type of resource.
    "apiUrl": "https://api.syncar.../"	// URL to updated resource in the Syncaroo API
  },
  "hash": "XXXX" 						// An encrypted hash of the data/payload to use as a signature verifying it's contents haven't been altered.
} 

Handling Status Sync change notifications

During the first lockdowns of 2020, Syncaroo released a free tier that allows workspaces to sync their current ‘workspace status’ to platforms. 

These webhooks have a slightly different schema.

Their headers contain the same: 

{
    "Authorization": "Bearer {{accessToken}}" // The access Token received from your platform
} 

But the body contents look a little something like this:

{
  "connectionId": 99, 		// Connection identifier
  "webhookType": "status", 	// Kind of webhook, can be either 'data' for Data Sync webhooks or 'status' for Status Sync webhooks
  "locationId": "1198", 	// Your internal identifier for the affected location.
  "metaData": { 
    "xxxx": "xxxx",			// See the Status Sync Webhook API docs for more info for expected Payload schemas.
  }
}
 

Authenticating with the Syncaroo API.

We’ve implemented a mandatory platform-to-platform OAuth authentication step, in order to ensure that only authorized platforms and integrations can fetch your users’ resources, pricing, and other business-critical data.

Through your Developer Portal, you’ll be able to generate an ID/key set, let’s quickly define those for use in further examples.

{
    "syncarooClientId": "xxyyzz", // The Client ID you got from the Syncaroo Dev Portal.
    "syncarooClientSecret": "..." // The Client Secret you got from the Syncaroo Dev Portal.
} 

Getting Syncaroo API Access Tokens

Much like when your users connect their accounts to Syncaroo, you’ll need to run through a quick one-time OAuth handshake to get access and refresh tokens for future API keys.

To start the process, generate a link to the following url:

https://app.syncaroo.com/api/authorize?clientId={{syncarooClientId}}&redirectUri={{redirectUrl}}&responseType=code&scope&state 

To clarify, you’d be appending the following GET parameters to the link:

{
    "clientId": "{{syncarooClientId}}", // the client ID you got from your Syncaroo Dev Portal.
    "redirectUri": "https://yourapp.com/confirm", // Where we can redirect your admin user back to with the Authorization code.
    "responseType": "code", // leave as is.
    "scope": "", // Leave as blank, not currently in use.
    "state": "" // Any variable(s) you'd like to pass through the OAuth process and back to your redirect_uri.
} 

On visiting that link, a successful authentication will redirect your admin user back to your redirect URL with the following GET parameters:

{
    "code": "...",  // The one-time Authorization code you can exchange for access and refresh tokens.
    "state": ""     // Any variable(s) you'd like to pass through the OAuth process and back to your redirect_uri.
} 

Using the provided code, your system should then send a POST request to

https://app.syncaroo.com/api/token 

Containing the following headers:

{
   "Content-Type": "application/x-www-form-urlencoded"
} 

And the following body parameters:

{
    "clientId": "{{syncarooClientId}}",			// The Syncaroo Client ID you got from your Dev Portal.
    "redirectUri": "https://...",					// The previously provided redirect URL.
    "clientSecret": "{{syncarooClientSecret}}",	// The Syncaroo Client Secret you got from your Dev Portal.
    "code": "{{AuthorizationCode}}", 				// The Authorization code you just received.
    "grantType": "authorization_code"				// Leave as is.
} 

A successful response will return the following parameters:

{
  "tokenType": "Bearer",	
  "expiresIn": 600,		// # of seconds before the `access_token` expires. Bearer tokens are designed to expire in 10 minutes.
  "accessToken": "XXXX",	// The Bearer token you can use to access Syncaroo API resources.
  "refreshToken": "XXXX"	// The Refresh token you can use to get a new 10-min Bearer token.
} 

Refreshing access tokens.

With access tokens being so short-lived, a <refresh_token> is provided to use as a form of single-use token to get new tokens. 

To get a new access token, send a POST request to:

https://app.syncaroo.com/api/token 

Containing the following headers:

{
   "Content-Type": "application/x-www-form-urlencoded"
} 

With the following body parameters:

{
    "clientId": "{{syncarooClientId}}",			// The Syncaroo Client ID you got from your Dev Portal.
    "clientSecret": "{{syncarooClientSecret}}",	// The Syncaroo Client Secret you got from your Dev Portal.
    "refreshToken": "{{syncarooRefreshToken}}",    // The Refresh token you have stored from last refresh or initial token request.
    "grantType": "refresh_token"					// Leave as is.
} 

Which, if successful, will once again return new token credentials like so:

{
  "tokenType": "Bearer",	
  "expiresIn": 600,		// # of seconds before the `access_token` expires. Bearer tokens are designed to expire in 10 minutes.
  "accessToken": "XXXX",	// The Bearer token you can use to access Syncaroo API resources.
  "refreshToken": "XXXX"	// The Refresh token you can use to get a new 10-min Bearer token.
} 

Fetching data via the Syncaroo API

All Data Sync webhooks contain a apiUrl parameter inside the data object. 

You can ping a GET request to that url, with your <syncarooAccessToken> (see below) in the header like so:

{
    "Authorization": "Bearer {{syncarooAccessToken}}", // The access Token received from your platform
    "Accept": "application/json"
} 

And you’ll receive back a response schema that looks a little something like this:

{
  "data": [
    {
      "xxx":"xxx"           // See docs on API endpoints for detailed data schemas.
    }
  ],
  "pages": {
    "count": 1,             // Integer. Total number of pages.
    "current": 1,           // Integer. Current page number.
    "first": "https://...", // String.  Prepared apiUrl for getting this page.
    "next": "https://...",  // String.  Prepared apiUrl for getting this page.
    "prev": "https://...",  // String.  Prepared apiUrl for getting this page.
    "last": "https://..."   // String.  Prepared apiUrl for getting this page.
  }
} 

With that response, you’ll be able to parse, schedule or process updates to you listings.

Got questions, concerns or suggestions?

We’re here to help, either start a chat conversation on the bottom right of this page, or send us an email.

small_c_popup.png

Private Beta Now Open

Request Access

Pre-registration
And we... *
Software being used.
GDPR Opt-in