25 May 22: Status Sync webhooks removed (deprecated since 2021)
4 Mar 22: Updated response_type to responseType under section 4.
12 Jul 21: Header notice swapped for changelog.
21 Mar 21: Variables standardized to camelCase.
12 Jan 21: Documentation Published.
Who are these dev docs 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.
Authentication flows
Syncaroo syncing with aggregators works through two-layers of authentication.
User authentication – how we create/verify accounts on your system for workspace operators.
Platform authentication – how we secure the data made available to just your platform.
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.
- Request developer access. (We'll need the details above).
- You'll get access to the Syncaroo Dev Portal.
- Handling your users' connections to Syncaroo.
- Prepare to receive authenticated update notifications (aka webhooks)
- Get Syncaroo API authentication tokens.
- Test the integration.
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.
"responseType": "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 webhooks Syncaroo sends out.
Handling webhook 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.
}
Also see: Webhook Schema docs.
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.
Live Availability, Bookings & Two-way Syncs
Setting up Availability, Bookings & 2-way Syncs
Availability & Booking Data for Resources / Inventory
Using our /v1/locations/{ID}/resources/{ID}/availability endpoint, you are able to request up to 3 months of availability per resource.
You can pass ?start=Y-m-d&end=Y-m-d if you want specific time ranges, otherwise, you will receive 90 days of data after today.
This ‘cache’ will allow for faster search on your end.
Primary Actions to Complete & Recommendations
- Using your existing connection to our API, retrieve and store availability for the time frame you allow searching in your platform using the endpoint above.
This data is separated by start and end datetime values to be easy to store for each day. - At the beginning of each day, add the new availability data for the day at the end of your time range. (Example below). Do this by searching availability with a time range parameter like the following for the additional day you need
GET /v1/locations/{ID}/resources/{ID}/availability?start=2021-12-08&end=2021-12-08
Example
- Let’s say you wanted 30 days of availability data for 1 or many inventory items like a meeting room.
- Query the availability endpoint similar to the following: /v1/locations/{ID}/resources/{ID}/availability?start=2021-12-01&end=2021-12-31
- When a new day arrives, you will want the data for January 1st, 2022. That way you still have your 30 days of data in the future that you want.
- As a result, query /v1/locations/{ID}/resources/{ID}/availability?start=2021-01-01&end=2021-01-01
- This way, you only need to add or update smaller pieces of data which reduces the load on your system and is much faster to process.
Notifications of Availability Changes
When bookings are made within the inventory system we will notify you of changes to the availability via a webhook.
Note: With Phase 1 complete, you will not need to do anything new to receive this webhook.
Primary Actions to Complete & Recommendations
Once the webhook is received with a change, parse the recurrence portion of the webhook:
"recurrence": {
"seriesStart": "2021-12-08T18:00:00.000Z",
"seriesEnd" : "2021-12-08T18:30:00.000Z",
"rRule" : null
},
- if recurrence->rRule is not null, then pull a completely new cache for the resource
- If recurrence->rRule is null, then refresh only the day(s) that the booking is made on. Add the start and end dates to the availability search similar to the above and replace that data in your cache.
Confirm Booking with 2-way Sync
Once a customer is ready to make a booking (2 way syncing), do the following:
Primary Actions to Complete & Recommendations
- Begin your typical process of booking on your end.
- Once you are ready to make the booking in the Operator’s system, send the booking details to us to confirm.
- Use our /v1/webhooks endpoint for the request
- We will either complete the booking with the operator or return an error if unsuccessful. If successful, your booking will now be added to the operator’s system.
- We will then respond with a success message and a booking reference in case you would need to modify or delete the booking in the future
Example
Let’s say that Jane would like to make a booking on your platform for 10:00 to 11:00 AM tomorrow.
When that user clicks to book, they complete the requirements on your end.
After these requirements have been completed such as adding a valid CC, filling in certain details, etc, send a notification(webhook) to our webhooks endpoint with the booking details.
Syncaroo will then go through all the processes of confirming whether the booking can be made or not. If the booking time frame is possible, we will make the booking and pass the booking details back to your platform immediately.
Webhooks
Syncaroo dispatches webhooks to notify integrated platforms about changes to mapped locations, resources, metadata, pricing and availability.
In short, webhooks will tell you about the change, what it affects (including your own unique identifiers) and a secured API url to fetch the updated information.
This wrapped URL provide an extra layer of security and allow for creative processing like batch updating of grouped changes.
You can learn more about our webhooks and see some examples here.
Unified API endpoints
A big benefit of working with Syncaroo is that we offer a unified API schema, regardless of what integrated management system(s) the workspace operator uses.
Current API endpoints
Locations
GET /v1/locations or GET /v1/locations/{ID}
Some sample data points:
"Name" // String. Location Name
"Description" // String. Location Description
"TimeZone" // String. Location Timezone
"syncOpenStatus" // String. Location's current lockdown status.
"address" // Array. Location's street address.
"hoursOfOperation" // Array. Operating day and hours.
Resources
GET /v1/locations/{ID}/resources or GET /v1/locations/{ID}/resources/{ID}
Some sample data points:
"description" // String. Resource description.
"type" // String. 'hot-desk', 'office', 'meeting-room', 'dedicated-desk', 'floor'
"units" //
"capacity" //
"Usage details" //
"size" // Integer. Size in sq ft.
"bookable" // Boolean. If is currently available for booking.
"availableFrom" // DateTime. When is next bookable.
Rates/Prices
GET /v1/locations/{ID}/resources/{ID}/rates
or
GET /v1/locations/{ID}/resources/{ID}/rates/{ID}
Available Extras
GET /v1/locations/{ID}/resources/{ID}/rates/{ID}/extras or GET /v1/locations/{ID}/resources/{ID}/rates/{ID}/extras/{ID}
Extras or addons for a specific rate for a resource (This often includes mailbox costs, lockers, or other services that are available for sale)
Files
GET /v1/locations/{ID}/resources/{ID}/files or GET /v1/locations/{ID}/resources/{ID}/files/{ID}
Primarily images for now, but will also include other types of files attached to resources.
Live Availability
GET /v1/locations/{ID}/resources/{ID}/availability
Returns booked / times unavailable for bookings. This data can be used for internal search / caching purposes.
Booking Confirmations
POST /v1/webhooks
Returns booked / times unavailable for bookings. This data can be used for internal search / caching purposes.