API Reference version v1

https://app.officernd.com/api/v1/organizations/{orgSlug}

Getting started

OfficeR&D public API is designed to let 3rd party applications communicate with OfficeR&D database.

The API is designed after the system entities - there is a separate resource for every entity and they can be listed, viewed by ID, added, updated by id and deleted by id.

Two APIs are available serving different purposes:

  • Server to server - available at /{resource}. Usually, used for integrating server-based applications.
    • Authentication - token-based
  • Client to server - available at /user/{resource} - Usually, used for integrating Mobile apps, Member portals, etc.
    • Authentication - authenticated as a user/member. In order to call any of the User APIs, you need to provide a valid Authorization token, received by /auth/signin endpoint.

Populating queries

Many objects contain the Id of a related object in their response properties. For example, a Visit may has an associated Visitor Id. Those objects can be expanded inline with the $populate request parameter.

Objects that can be expanded are noted in this documentation. This parameter is available on all GET API requests. This option work for both object lists or requesting single object by id.

Selecting fields

Often you don't need all the fields of a given object and you just transfer them without ever using them. You can optimize such quieries by passing the $select request parameter.

This parameter is available on all GET API requests. This option work for both object lists or requesting single object by id.

Filtering results

You can filter results of every collection request by adding query parameters. For example, if you want to find all members which are part of a company you can add team=<teamId> in the query string.

Wildcard matches

For some string properties you can use wildcard matches if you want to find a group of entites. If you want to do wildcard search you can use $sw, $ew, $cs for starts with, ends with and contains matches. If you need to perform case insensitive search, just use $swi, $ewi and $csi.

Now, if you want to find all members with name starting with "john" no matter the case you can pass name.$swi=john.

Please notice that as these are query parameters their values need to be URL encoded.

Entity Schema

We provide schemas for all entities referenced in these API docs. Please note that entities might contain different properties than the schema, i.e. they might have additional properties (not documented ones) or might have missing some of the optional properties.

We explicitly document ONLY the properties we think should be used by external systems and we will keep compatibility when rolling out new versions of the API. All not documented properties are considered internal for the system and might be subject of change without changing the API version or notification.

This means you should not use any properties which are not included in the entity schema as they are considered internal for the system.

Bearer token authentication

Authentication against the OfficeR&D API is done bearer token which is unique by organization. To acquire a token please contact us at support@officernd.com and we will generate one for you.

Authorization header

Once you have the token you need to add an Authorization header to every request. The value of the header should be "Bearer <token>". It should look like this:

  Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU4NDZmMjhhZmY1ZDg4MTI2YWJjZmMzZiIsImlhdCI6MTQ4MTExNjQwOCwiZXhwIjoxNDgxMjg5MjA4fQ.ElceBwjTRBhu669SWkn_Za8VKk-cwomzmbEsNywPt5A

HTTP responses

401

Bad or expired token. This can happen if the token is too old (more than 1 year) or one of the admins requested the token to be revoked. Just contact us to reissue the token.

403

Bad or missing token. You either not provided the token or it doesn't give you permission for the organization in hand. Please contact us at support@officernd.com and we will assist you further.

Offices

Office objects represent the separate physical locations in the organization. They are used to separate resources and members in a single organization.

Office

PropertyTypeRequiredDescription
namestringtrueThe name of the plan in hand. It appears everywhere in the system.
countrystringfalseThe country part of the location address.
statestringfalseThe state part of the location address.
citystringfalseThe city part of the location address.
addressstringfalseThe address part of the location address.
zipstringfalseThe zip code part of the location address.
timezonestringfalseThe timezone the location is at.
imagestringfalseThe URL pointing to an image assigned to this location.
isOpenbooleanfalseIf true, the location is operational; if false or ommited the location is not working - either not open yet, or suspended for some other reason.

/offices

get

Retrieve all locations in the space.

Query Parameters

  • name: (string)

    The exact name of the item you are looking for.

HTTP status code 200

Body

Type: application/json

Example:

[{
    "_id": "565748274a955c790d808c77",
    "slug": "shoreditch",
    "name": "Shoreditch",
    "city": "London",
    "image": "//dzrjcxtasfoip.cloudfront.net/user-resources/organization/-c62c.jpeg",
    "address": "1 Old Street",
    "timezone": null,
    "isOpen": true
}, {
    "_id": "57575786849afaf41b0294f9",
    "slug": "soho",
    "name": "Soho",
    "city": "London",
    "image": "//dzrjcxtasfoip.cloudfront.net/user-resources/organization/-4e45.jpeg",
    "address": "",
    "description": "12 Soho Square",
    "isOpen": true
}]

/offices/{officeId}

Retrieve an individual location.

get

Get the plan with id = {officeId}

URI Parameters

  • officeId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
    "_id": "565748274a955c790d808c77",
    "slug": "shoreditch",
    "name": "Shoreditch",
    "city": "London",
    "image": "//dzrjcxtasfoip.cloudfront.net/user-resources/organization/-c62c.jpeg",
    "address": "1 Old Street",
    "timezone": null,
    "isOpen": true
}

HTTP status code 404

Body

Type: application/json

Example:

{ "message": "Office not found" }

Members

Member objects allow you to keep your member's data in a single place, track memberships, invoices, charges, fees, and etc. Everything that is associated with the same customer.

The API allows you to create, delete, and update your members. You can retrieve individual members as well as a list of all your members.

Here is the list of all properties the member object has:

PropertyTypeRequiredDescription
namestringtrueThe full name of the member
emailstringtrueThe email address of the member
phonestringfalseThe primary phone number of the member
twitterHandlestringfalseThe twitter handle of the member
teamidfalseReference to the team the member belongs to
contactPersonbooleanTrue if the member is a contact persion in its company
billingPersonbooleanTrue if the member is the billing person of its company and recieves all the invoices
officeidfalseReference to the location the member belongs to. It will default to the only location if left empty
paymentDetailsarrayreadonlyArray containing all the names of the payment details added to the member account

/members

get

Retrieve all members.

Query Parameters

  • office: (string)

    Filter by office id.

  • team: (string)

    Filter by team id

  • name: (string)

    The exact name of the item you are looking for.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "name": "John Doe",
  "email": "john@doe.com",
  "team": "565748274a955c790d808c77",
  "phone": "+442130172"
}]
post

Add a new member.

Body

Type: application/json

Example:

[{
  "name": "John Doe",
  "email": "john@doe.com",
  "team": "565748274a955c790d808c77",
  "phone": "+442130172"
}]

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "name": "John Doe",
  "email": "john@doe.com",
  "team": "565748274a955c790d808c77",
  "phone": "+442130172"
}]
delete

You can delete members by passing array of IDs to be deleted as request body.

Body

Type: application/json

Example:

["57a1a8d8c334490c73b2856f"]

/members/{memberId}

Retrieve an individual member.

get

Get the member with id = {memberId}

URI Parameters

  • memberId: required (string)

    The Id of the corresponding member

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "57a1a8d8c334490c73b2856f",
  "name": "John Doe",
  "email": "john@doe.com",
  "team": "565748274a955c790d808c77",
  "phone": "+442130172"
}

HTTP status code 404

Body

Type: application/json

Example:

{
  "message": "Member not found"
}

Teams

Team objects allow you to keep your companies' data in single place, track memberships, invoices, charges, fees, and etc.

Everything that is associated with the same customer. The API allows you to create, delete, and update your companies / teams. You can retrieve individual teams as well as a list of all your teams.

Here is the list of all properties the team object has:

PropertyTypeRequiredDescription
namestringtrueThe full name of the member
emailstringtrueThe email address of the member
twitterHandlestringfalseThe twitter handle of the member
officeidfalseReference to the location the member belongs to. It will default to the only location if left empty
paymentDetailsarrayreadonlyArray containing all the names of the payment details added to the member account

/teams

get

Retrieve all teams.

Query Parameters

  • office: (string)

    Filter by office id.

  • name: (string)

    The exact name of the item you are looking for.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "name": "OfficeR&D",
  "email": "info@officernd.com".
  "properties": {
    "description": "Coworking management platform for prosperous communities and efficient workspaces"
  }
}]
post

Add new members

Body

Type: application/json

Example:

[{
  "name": "OfficeR&D",
  "email": "info@officernd.com",
  "properties": {
    "description": "Coworking management platform for prosperous communities and efficient workspaces"
  }
}]

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "name": "OfficeR&D",
  "email": "info@officernd.com",
  "properties": {
    "description": "Coworking management platform for prosperous communities and efficient workspaces"
  }
}]
delete

You can delete teams by passing array of IDs to be deleted as request body.

Body

Type: application/json

Example:

["57a1a8d8c334490c73b2856f"]

/teams/{teamId}

Individual team.

get

Retreive the team with id = {teamId}

URI Parameters

  • teamId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "57a1a8d8c334490c73b2856f",
  "name": "OfficeR&D",
  "email": "info@officernd.com",
  "properties": {
    "description": "Coworking management platform for prosperous communities and efficient workspaces"
  }
}

HTTP status code 404

Body

Type: application/json

Example:

{ "message": "Team not found" }
put

Update the team with id = {teamId}

URI Parameters

  • teamId: required (string)

Body

Type: application/json

Example:

{
    "name": "John Smith Corp",
    "properties": {
        "Other": "Some additional info"
    }
}

HTTP status code 200

Body

Type: application/json

Example:

{
    "createdAt": "2017-09-05T11:18:03.148Z",
    "createdBy": "59ae87e92dc0286c3e38bd8c",
    "name": "John Smith Corp",
    "description": "",
    "image": null,
    "email": "john.smith@gmail.com",
    "office": "59a831f7385a0d1400f325f6",
    "_id": "59ae87eb2dc0286c3e38bd8d",
    "properties": {
        "Other": "Some additional info",
        "AccountNumber": "1234"
    },
    "details": {
        "date": null,
        "name": "Mr. John Smith"
    },
    "files": [],
    "tags": [],
    "twitterInfo": {
        "imageUrl": null,
        "description": ""
    },
    "isTeam": true
}

Memberships

Membership objects allow you to assign recurring charges (price plans) to individual members or teams. The API allows you to create, delete, and update your memberships. You can retrieve individual memberships as well as a list of all your memberships.

/memberships

get

Retrieve all memberships.

Query Parameters

  • $populate: (string)

    Comma-separated list of all properties to be populated. Only id references can be populated. Refer to Populating queries section for more information.

  • team: (string)

    Filter by team id

  • member: (string)

    Filter by member id

/memberships/{memberhipId}

Retrieve individual membership.

get

Get the member with id = {membershipId}

URI Parameters

  • memberhipId: required (string)

Query Parameters

  • $populate: (string)

    Comma-separated list of all properties to be populated. Only id references can be populated. Refer to Populating queries section for more information.

Bookings

Bookings are short-term reservation of resource. Bookings can reserve any resource, such as Meeting Room, Hot desk, Private Office, etc.

The API allows you to create, delete, and update bookings.

Here is the list of most properties the booking:

Booking

PropertyTypeRequiredDescription
start.dateTimedatetrueStart datetime of the booking
end.dateTimedatetrueEnd datetime of the booking
timezonestringfalseThe booking timezone
sourcestringfalseThe origin/source of the booking
summarystringfalseBooking title/summary
resourceIdidtrueReference to the booked resource
planidfalseReference to the resource rate used for the booking.
teamidfalseReference to the company (required if no member)
memberidfalseReference to the member (required if no team)
descriptionstringfalseLong description of the booking
tentativebooleanfalseTrue if the booking is not confirmed. Tentative booking are not charged.
freebooleanfalseTrue if the booking is marked as free. If create a booking marked as free, no fees will be added for it.
feesarrayreadonlyArray of items describing how the booking will be charged for. Described below as BookingFee.
extrasobjectfalseDictionary with keys the IDs of the extras to add to the booking and values - the quantity of the extra

Booking Fee

PropertyTypeRequiredDescription
datedatetrueThe date of the occurrence the fee has been generated for
feeFeefalseThe actual charge generated for this occurrence.
creditsarraytrueThe credits used to do the booking
extraFeesarray(Fee)trueArray of fees generated for the extras.

/bookings

get

Retrieve all bookings.

Query Parameters

  • office: (string)

    Filter by office id.

  • member: (string)

    Filter by member id

  • team: (string)

    Filter by team id

post

Add one or many bookings.

Body

Type: application/json

Example:

[{
  "team": "57a1a8d8c334asdafc73b2856f",
  "member": "57a1a8d8c334asdafc73safag6f",
  "start": {
    "dateTime": "2017-10-31T09:00:00.000Z"
  },
  "end": {
    "dateTime": "2017-05-31T11:00:00.000Z"
  },
  "resourceId": "58e3414e60b481c648202848",
  "summary": "First booking"
}, {
  "team": "57a1a8d8c334asdafc73b2856f",
  "member": "57a1a8d8c334asdafc73safag6f",
  "start": {
    "dateTime": "2017-05-31T13:00:00.000Z"
  },
  "end": {
    "dateTime": "2017-05-31T14:00:00.000Z"
  },
  "resourceId": "58e3414e60b481c648202848",
  "summary": "Second booking"
  }
}]

HTTP status code 200

Body

Type: application/json

Example:

[{
    "start": {
      "dateTime": "2017-10-31T09:00:00.000Z"
    },
    "end": {
      "dateTime": "2017-10-31T11:00:00.000Z"
    },
    "resourceId": "5943b5ebb4bd93ca5f1906fc",
    "extras": {},
    "recurrence": {
      "rrule": null
    },
    "member": null,
    "visitors": [],
    "members": [],
    "team": "59493231518f3f150d306c62",
    "timezone": "Europe/London",
    "source": "admin",
    "plan": "5943b59eb4bd93ca5f1906f7",
    "fees": [{
      "date": "2017-10-31T00:00:00.000Z",
      "extraFees": [],
      "credits": [{
        "count": 2,
        "credit": "594932ea518f3f150d306c89"
      }]
    }],
    "accountedUntil": null
  }, {
    "start": {
      "dateTime": "2017-10-31T13:00:00.000Z"
    },
    "end": {
      "dateTime": "2017-10-31T14:00:00.000Z"
    },
    "resourceId": "5943b5ebb4bd93ca5f1906fc",
    "extras": {},
    "recurrence": {
      "rrule": null
    },
    "member": null,
    "visitors": [],
    "members": [],
    "team": "59493231518f3f150d306c62",
    "timezone": "Europe/London",
    "source": "admin",
    "plan": "5943b59eb4bd93ca5f1906f7",
    "fees": [{
      "date": "2017-10-31T00:00:00.000Z",
      "extraFees": [],
      "credits": [{
        "count": 1,
        "credit": "594932ea518f3f150d306c89"
      }]
    }],
    "accountedUntil": null
  }]

/bookings/checkout

Booking checkout endpoint is used to automatically pick resources for booking based on a booking request. It can be used when it doesn't matter which resource should be booked, but it is more important certain criterias to be matched.

Booking Request

PropertyTypeRequiredDescription
startdatetrueStart datetime of the booking request.
enddatetrueEnd datetime of the booking request.
teamidfalseReference to the company (required if no member).
memberidfalseReference to the member (required if no team).
extrasobjectfalseDictionary with keys the IDs of the extras to add to the booking and values - the quantity of the extra.
sourcestringfalseThe origin/source of the bookings.
summarystringfalseBooking title/summary.
descriptionstringfalseLong description of the booking.
tentativebooleanfalseTrue if the booking is not confirmed. Tentative booking are not charged.
freebooleanfalseTrue if the booking is marked as free. If create a booking marked as free, no fees will be added for it.
sizenumber*falseThe resource size to used.
countnumbertrueThe count of bookings of this type to be made.
rateidfalseThe resource rate to be used to lookup available resources.
resourceTypeidfalseThe resource type to be used to lookup available resources.

number*: You can use a query instead of a value, for example { size: { $gte: 2 } }, meaning the size must be at least 2

post

Create bookings without specifing resources, but search parameters instead. The request is of type Booking Request and the result is an array of Booking.

Body

Type: application/json

Example:

[{
	"start": "2017-11-11T17:00:00Z",
	"end": "2017-11-11T18:00:00Z",
	"count": 2,
	"team": "5a1ec6b9825f901400025780",
	"summary": "title of the booking",
	"description": "description of the booking - book 2 meeting rooms with 5 coffees each",
	"resourceType": "meeting_room",
	"extras": {
		"59cbbb2d863e7014004879b6": 5
	}
}, {
	"start": "2017-11-11T17:00:00Z",
	"end": "2017-11-11T18:00:00Z",
	"count": 2,
	"team": "5a1ec6b9825f901400025780",
	"summary": "title of the booking",
	"description": "description of the booking - book 2 dedicated desks",
	"resourceType": "desk"
}, {
	"start": "2017-11-11T17:00:00Z",
	"end": "2017-11-11T18:00:00Z",
	"count": 2,
	"team": "5a1ec6b9825f901400025780",
	"summary": "title of the booking",
	"description": "description of the booking - book 2 hotdesks",
	"resourceType": "hotdesk"
}, {
	"start": "2017-11-11T17:00:00Z",
	"end": "2017-11-11T18:00:00Z",
	"count": 2,
	"team": "5a1ec6b9825f901400025780",
	"summary": "title of the booking",
	"description": "description of the booking - book 2 phonebooths with only rates",
	"rate": "59cba40ac1798a14001ada01"
}]

HTTP status code 200

Body

Type: application/json

Example:

[{
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "5a0c43d93237881400d15919",
        "description": "description of the booking - book 2 meeting rooms with 5 coffees each",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "59cb9e44c1798a14001ad350",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca58",
        "extras": {
            "59cbbb2d863e7014004879b6": 5
        },
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca46",
            "extraFees": [
                "5a1edc45adae3a140069ca47"
            ],
            "credits": []
        }]
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "5a1eb96db7ca79140096c45b",
        "description": "description of the booking - book 2 meeting rooms with 5 coffees each",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "59cb9e44c1798a14001ad350",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca59",
        "extras": {
            "59cbbb2d863e7014004879b6": 5
        },
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca42",
            "extraFees": [
                "5a1edc45adae3a140069ca43"
            ],
            "credits": []
        }]
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "59cba49cc1798a14001ada21",
        "description": "description of the booking - book 2 dedicated desks",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5a",
        "members": [],
        "visitors": [],
        "fees": []
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "59cba4a57de35214002d9fb9",
        "description": "description of the booking - book 2 dedicated desks",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5b",
        "members": [],
        "visitors": [],
        "fees": []
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "59cba4ae7de35214002d9fbc",
        "description": "description of the booking - book 2 hotdesks",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5c",
        "members": [],
        "visitors": [],
        "fees": []
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "59cba4b5c1798a14001ada25",
        "description": "description of the booking - book 2 hotdesks",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "5a1e90b10d8de714006d2e85",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5d",
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca44",
            "extraFees": [],
            "credits": []
        }]
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "5a1ec833825f9014000257db",
        "description": "description of the booking - book 2 phonebooths with only rates",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "59cba40ac1798a14001ada01",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5e",
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca45",
            "extraFees": [],
            "credits": []
        }]
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "5a1ec83fadae3a140069c8df",
        "description": "description of the booking - book 2 phonebooths with only rates",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "59cba40ac1798a14001ada01",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5f",
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca49",
            "extraFees": [],
            "credits": []
        }]
    }
]

/bookings/{bookingId}

Retrieve a booking by ID.

get

Get the booking with id = {bookingId}

URI Parameters

  • bookingId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
  "start": { "dateTime": "2017-07-11T11:30:00.000Z" },
  "end": { "dateTime": "2017-07-11T12:00:00.000Z" },
  "timezone": "Europe/London",
  "source": "portal",
  "recurrence": { "rrule": null },
  "fees": [{ "date": "2017-07-11T00:00:00.000Z", "credits": [], "fee": { "_id": "5963c6d3d145045357a22cf1", "name": "Small Conference Room, 0.5 x £4.00 / hour - Jul 11, 2017", "price": 4, "quantity": 0.5, "invoice": { "status": "not_paid" } }, "extraFees": [{ "_id": "5963c6d3d145045357a22cf2", "name": "Extra", "price": 6, "quantity": 1, "invoice": { "status": "not_paid" } }] }],
  "resourceId": "5963817ab75f6fa2450756b1",
  "team": "5943fdb5772a5ce96552a488",
  "member": "5911c5fefb2465366be4b157",
  "visitors": [],
  "members": [],
  "plan": "5943b59eb4bd93ca5f1906f7",
  "extras": { "59480b70b41f0dd0b54ce1b7": 1 },
  "credits": [],
  "extraFees": [],
  "accountedUntil": null,
  "_id": "5963c6d3d145045357a22cf3"
}
put

Update the booking with id = {bookingId}

URI Parameters

  • bookingId: required (string)

Body

Type: application/json

Example:

{
  "_id": "5963c6d3d145045357a22cf3",
  "title": "Update"
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "start": { "dateTime": "2017-07-11T11:30:00.000Z", "date": null },
  "end": { "dateTime": "2017-07-11T12:00:00.000Z", "date": null },
  "timezone": "Europe/London",
  "source": "portal",
  "summary": "Update",
  "resourceId": "5963817ab75f6fa2450756b1",
  "team": "5943fdb5772a5ce96552a488",
  "member": "5911c5fefb2465366be4b157",
  "plan": "5943b59eb4bd93ca5f1906f7",
  "accountedUntil": null,
  "_id": "5963c6d3d145045357a22cf3",
  "extraFees": [],
  "credits": [],
  "extras": { "59480b70b41f0dd0b54ce1b7": 1 },
  "members": [],
  "visitors": [],
  "fees": [{ "date": "2017-07-11T00:00:00.000Z", "fee": "5964f000ca6c7ca8782cd267", "extraFees": ["5964f000ca6c7ca8782cd268"], "credits": [] }],
  "recurrence": { "rrule": null }
}
delete

Delete a booking with id = {bookingId}. Deleting the booking will remove the assiciated fees and will return the used credits the the company/member account.

URI Parameters

  • bookingId: required (string)

/bookings/summary

post

Validate a booking and returns if the booking is valid and any charges, fees, or credits will be used.

Booking Summary

PropertyTypeRequiredDescription
targetBooking TargetfalseObject, describing the member and company, which are about to create a booking.
bookingBookingfalseThe booking to be validated if possible to be created without the team and member properties (required if bookings is not passed).

Booking Target

PropertyTypeRequiredDescription
teamidfalseThe ID of the team in hand
memberidfalseThe ID of the member in hand

Body

Type: application/json

Example:

{
  "booking": {
    "start": {
      "dateTime": "2017-05-31T09:00:00.000Z"
    },
    "end": {
      "dateTime": "2017-05-31T11:00:00.000Z"
    },
    "resourceId": "58e3414e60b481c648202848",
    "summary": "Meeting Room booking info"
  },
  "target": {
    "team": "57a1a8d8c334asdafc73b2856f",
    "member": "57a1a8d8c334asdafc73safag6f"
  }
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "start": {
    "dateTime": "2017-07-11T16:30:00.000Z"
  },
  "end": {
    "dateTime": "2017-07-11T17:30:00.000Z"
  },
  "resourceId": "5943b5ebb4bd93ca5f1906fc",
  "extras": {},
  "recurrence": {
    "rrule": null
  },
  "member": null,
  "visitors": [],
  "members": [],
  "team": "59493231518f3f150d306c62",
  "timezone": "Europe/London",
  "source": "admin",
  "plan": "5943b59eb4bd93ca5f1906f7",
  "fees": [{
    "date": "2017-07-11T00:00:00.000Z",
    "extraFees": [],
    "credits": [{
      "count": 1,
      "credit": "594932ea518f3f150d306c89"
    }]
  }],
  "accountedUntil": null
}

HTTP status code 400

Body

Type: application/json

Example:

{
  "name": "InvalidOperationError",
  "message": "Resource is not available in this time slot.",
  "type": "Invalid operation",
  "details": {
    "messages": ["Resource is not available in this time slot."]
  }
}

/bookings/checkout-summary

post

Validate a booking request and returns fees or credits that will be used. Accepts Booking Request as body and returns an array of Booking.

Body

Type: application/json

Example:

{
	"start": "2017-11-11T17:00:00Z",
	"end": "2017-11-11T18:00:00Z",
	"count": 2,
	"team": "5a1ec6b9825f901400025780",
	"summary": "title of the booking",
	"description": "description of the booking - book 2 phonebooths with only rates",
	"rate": "59cba40ac1798a14001ada01"
}

HTTP status code 200

Body

Type: application/json

Example:

[{
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "5a1ec833825f9014000257db",
        "description": "description of the booking - book 2 phonebooths with only rates",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "59cba40ac1798a14001ada01",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5e",
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca45",
            "extraFees": [],
            "credits": []
        }]
    },
    {
        "start": {
            "dateTime": "2017-11-11T17:00:00.000Z"
        },
        "end": {
            "dateTime": "2017-11-11T18:00:00.000Z"
        },
        "summary": "title of the booking",
        "resourceId": "5a1ec83fadae3a140069c8df",
        "description": "description of the booking - book 2 phonebooths with only rates",
        "team": "5a1ec6b9825f901400025780",
        "timezone": "Europe/London",
        "plan": "59cba40ac1798a14001ada01",
        "accountedUntil": null,
        "createdBy": "5a1ebb8ed75ffb140046daa8",
        "createdAt": "2017-11-29T16:11:49.879Z",
        "_id": "5a1edc45adae3a140069ca5f",
        "members": [],
        "visitors": [],
        "fees": [{
            "date": "2017-11-11T00:00:00.000Z",
            "fee": "5a1edc45adae3a140069ca49",
            "extraFees": [],
            "credits": []
        }]
    }
]

/bookings/occurrences

get

Get a list of all occurrences for a specified period.

Query Parameters

  • office: (string)

    Filter by office id.

  • member: (string)

    Filter by member id

  • team: (string)

    Filter by team id

  • start: required (date)

    Start of the interval to get occurrences for

  • end: required (date)

    End of the interval to get occurrences for

HTTP status code 200

Body

Type: application/json

Example:

[{
  "start": { "dateTime": "2017-07-11T11:30:00.000Z" },
  "end": { "dateTime": "2017-07-11T12:00:00.000Z" },
  "timezone": "Europe/London",
  "source": "portal",
  "recurrence": { "rrule": null },
  "fees": [{ "date": "2017-07-11T00:00:00.000Z", "credits": [], "fee": { "_id": "5963c6d3d145045357a22cf1", "name": "Small Conference Room, 0.5 x £4.00 / hour - Jul 11, 2017", "price": 4, "quantity": 0.5, "invoice": { "status": "not_paid" } }, "extraFees": [{ "_id": "5963c6d3d145045357a22cf2", "name": "Extra", "price": 6, "quantity": 1, "invoice": { "status": "not_paid" } }] }],
  "resourceId": "5963817ab75f6fa2450756b1",
  "team": "5943fdb5772a5ce96552a488",
  "member": "5911c5fefb2465366be4b157",
  "visitors": [],
  "members": [],
  "plan": "5943b59eb4bd93ca5f1906f7",
  "extras": { "59480b70b41f0dd0b54ce1b7": 1 },
  "credits": [],
  "extraFees": [],
  "accountedUntil": null,
  "_id": "5963c6d3d145045357a22cf3"
}]

Fees

Fee objects describe one-off charges or groups of one-off charges. They might or might not be connected to a specific plan, but must have their own name and price.

You can retrieve individual fee as well as query all the fees by location, company or member.

Here is the list of all properties the fee object has:

Fee

PropertyTypeRequiredDescription
namestringtrueThe name of the charge. It will appear in the invoice line item.
pricenumbertrueThe unit price of the item described by the fee.
datedatetrueThe date when the service has been sold. This date is used to determine in which invoice the fee should be included.
teamidfalseA reference to the company the invoice is issued for.
memberidfalseA reference to the member or individual the invoice is issued for.
officeidtrueA reference to the location the invoiced is issued by.
quantitynumberfalseThe quantity described by the one-off charge. If ommited, 1 is assumed.
planidfalseA reference to the price plan assigned to the fee. It is used to determine the sales account when generating an invoice.
refundablebooleanfalseIf true, the one-off charge is counted as deposit and can be refuded later on.
billInAdvancebooleanfalseIf true, the one-off charge is is billed in advance (respecting its date). By default one-off charges are billed in arears.
isPersonalbooleanfalseIf true, the one-off charge is is billed to the assigned member and not to the company.

/fees

get

Retrieve all fee objects

Query Parameters

  • member: (string)

    Filter by member id

  • team: (string)

    Filter by team id

  • office: (string)

    Filter by office id.

  • $populate: (string)

    Comma-separated list of all properties to be populated. Only id references can be populated. Refer to Populating queries section for more information.

HTTP status code 200

Body

Type: application/json

Example:

[{
    "_id": "58ac916ba372d96504057a65",
    "refundable": false,
    "billInAdvance": true,
    "name": "Day pass",
    "price": 30,
    "plan": "5885f3953eefcdc52755a6a0",
    "team": "565363aa3492382393f68e7c",
    "office": "565748274a955c790d808c77",
    "date": "2017-02-21T00:00:00.000Z",
    "quantity": 5
}]
post

Add multiple fee objects.

Body

Type: application/json

Example:

[{
    "billInAdvance": true,
    "name": "Day pass",
    "price": 30,
    "plan": "5885f3953eefcdc52755a6a0",
    "team": "565363aa3492382393f68e7c",
    "office": "565748274a955c790d808c77",
    "date": "2017-02-21T00:00:00.000Z",
    "quantity": 5
}]

HTTP status code 200

Body

Type: application/json

Example:

[{
    "_id": "58ac916ba372d96504057a65",
    "refundable": false,
    "billInAdvance": true,
    "name": "Day pass",
    "price": 30,
    "plan": "5885f3953eefcdc52755a6a0",
    "team": "565363aa3492382393f68e7c",
    "office": "565748274a955c790d808c77",
    "date": "2017-02-21T00:00:00.000Z",
    "quantity": 5
}]

/fees/{feeId}

Retrieve an individual fee object.

get

Get the fee object with id = {feeId}

URI Parameters

  • feeId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
    "_id": "58ac916ba372d96504057a65",
    "refundable": false,
    "billInAdvance": true,
    "name": "Day pass",
    "price": 30,
    "plan": "5885f3953eefcdc52755a6a0",
    "team": "565363aa3492382393f68e7c",
    "office": "565748274a955c790d808c77",
    "date": "2017-02-21T00:00:00.000Z",
    "quantity": 5
}

HTTP status code 404

Body

Type: application/json

Example:

{
  "message": "Fee not found"
}
put

Update the fee object with id = {feeId}

URI Parameters

  • feeId: required (string)

Body

Type: application/json

Example:

{
    "price": 35,
}

HTTP status code 200

Body

Type: application/json

Example:

{
    "_id": "58ac916ba372d96504057a65",
    "refundable": false,
    "billInAdvance": true,
    "name": "Day pass",
    "price": 35,
    "plan": "5885f3953eefcdc52755a6a0",
    "team": "565363aa3492382393f68e7c",
    "office": "565748274a955c790d808c77",
    "date": "2017-02-21T00:00:00.000Z",
    "quantity": 5
}

HTTP status code 404

Body

Type: application/json

Example:

{
  "message": "Fee not found"
}
delete

Remove the fee object with id = {feeId}

URI Parameters

  • feeId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
    "_id": "58ac916ba372d96504057a65",
    "refundable": false,
    "billInAdvance": true,
    "name": "Day pass",
    "price": 35,
    "plan": "5885f3953eefcdc52755a6a0",
    "team": "565363aa3492382393f68e7c",
    "office": "565748274a955c790d808c77",
    "date": "2017-02-21T00:00:00.000Z",
    "quantity": 5
}

HTTP status code 404

Body

Type: application/json

Example:

{
  "message": "Fee not found"
}

Plans

Plan objects (or price plans) allow you to create one-off or recurring named charges.

You can retrieve individual plans as well as a list of all your plans.

Plan

PropertyTypeRequiredDescription
namestringtrueThe name of the plan in hand. It appears everywhere in the system.
descriptionstringfalseText describing the plan. It will appear when users need to choose among different plans.
pricenumbertrueThe default unit price for the plan, depending if it is recurring plan or a one-off plan.
locations[id]trueList of all locations where the plan is present. If empty, all locations are assumed.
typeenumtrueThe type of the plan. It could be office, desk, hotdesk or service.
intervalLengthenumtrueThe plan interval. It could be month or once.
codestringfalseExternal identified for the plan. Usually used for accounting purposes.

NOTE: Right now the plans API returns both rates and plans, so you should ignore all items with isRate property set to true

/plans

get

Retrieve all plans.

Query Parameters

  • name: (string)

    The exact name of the item you are looking for.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "",
  "name": "Dedicated desk",
  "description": "Fixed desk for member, suitable for full-time members",
  "intervalLenght": "month",
  "price": "200",
  "deposit": "200",
  "addOns": []
}]

/plans/{planId}

Retrieve an individual plan.

get

Get the plan with id = {planId}

URI Parameters

  • planId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "",
  "name": "Dedicated desk",
  "description": "Fixed desk for member, suitable for full-time members",
  "intervalLenght": "month",
  "price": "200",
  "deposit": "200",
  "addOns": []
}

HTTP status code 404

Body

Type: application/json

Example:

{"message": "Plan not found"}

Rates

Rate objects (or resource rates) describe available resource rates in the system. Rates are very similar to the plans.

/rates

get

Retrieve all resource rates.

Query Parameters

  • name: (string)

    The exact name of the item you are looking for.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "59a832dc385a0d1400f32619",
  "name": "Room Rate",
  "price": 20,
  "cancellationPolicy": {
    "minimumPeriod": 24
  },
  "extras": [{
    "_id": "59a832ea48185f140085680c",
    "name": "Coffee",
    "price": 2
  }],
  "maxDuration": 24
}]

/rates/{rateId}

Retrieve an individual rate.

get

Get the rate with id = {rateId}

URI Parameters

  • rateId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "59a832dc385a0d1400f32619",
  "name": "Room Rate",
  "price": 20,
  "cancellationPolicy": {
    "minimumPeriod": 24
  },
  "extras": [{
    "_id": "59a832ea48185f140085680c",
    "name": "Coffee",
    "price": 2
  }],
  "maxDuration": 24
}

Resources

Resource objects describe all type of bookable (short term bookings or long term assignments) resources in the system.

Resource types can be extended and modified, but the default ones are:

  • meeting rooms - meeting_room
  • private offices - team_room
  • private office desk - desk_tr
  • dedicated desks - desk
  • hot desks - hotdesk

You can retrieve individual resources as well as a list of all your resources or all of a specific type.

Resource

PropertyTypeRequiredDescription
namestringtrueThe name of the resource in hand.
rateratefalseThe resource rate used for pricing bookings for this particualr resource.
officeidtrueThe location the resource is assigned to
roomidtrueThe floorplan the resource is assigned to
typeenumtrueThe type of the resource. One of types listed above.

/resources

get

Retrieve all resources.

Query Parameters

  • office: (string)

    Filter by office id.

  • name: (string)

    The exact name of the item you are looking for. Also, you can use this property to perform a wildcard match.

  • type: (string)

    One of the possible resource types.

  • availableFrom: (date)

    Query available resources from the specified date.

  • availableTo: (date)

    Query available resources to the specified date.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "56535da73492382393f68e2b",
  "name": "1-1",
  "room": "5804f7935a8e12f92e8694f3",
  "targetPlan": null,
  "office": "57575786849afaf41b0294f9",
  "type": "desk"
}]

/resources/{resourceId}

Retrieve individual resource.

get

Get the resource with id = {resourceId}

URI Parameters

  • resourceId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "56535da73492382393f68e2b",
  "name": "1-1",
  "room": "5804f7935a8e12f92e8694f3",
  "targetPlan": null,
  "office": "57575786849afaf41b0294f9",
  "type": "desk_tr"
}

HTTP status code 404

Body

Type: application/json

Example:

{ "message": "Resource not found" }

Contracts

Contract objects allow you to associate contract data to your companies. Contracts can contain terms for both Services and Private offices. The API allows you to create, delete, and update contracts. You can retrieve individual contracts as well as a list of all your contracts.

/contracts

get

Retrieve all contracts.

Query Parameters

  • team: (string)

    Filter by team id

  • office: (string)

    Filter by office id.

HTTP status code 200

Body

Type: application/json

Example:

[{
    "_id": "58c45aa1261dd205c275bc78",
    "team": "58736fbda872255b08624f40",
    "office": "5873945c3ad3dd0e101ffa04",
    "startDate": "2017-03-11T00:00:00.000Z",
    "renewalDate": "2018-03-11T00:00:00.000Z",
    "number": "CON-MNCHSTR-1",
    "plans": [],
    "resources": [
      {
        "id": "5873960d3ad3dd0e101ffa3b",
        "listPrice": 500,
        "price": 300
      }
    ],
    "memberships": [
      "58c45aa4261dd205c275bc7b"
    ],
    "notice": {
      "months": 3
    },
    "status": "signed"
}]
post

Add new contracts

Body

Type: application/json

Example:

{
	"startDate": "2018-01-30T00:00:00.000Z",
	"endDate": "2019-01-29T00:00:00.000Z",
	"office": "5a13f0437bab08ac23b269d4",
	"notice": {
		"months": 3
	},
	"type": "new",
	"resources": [{
		"steps": [{
			"startDate": "2018-01-30T00:00:00.000Z",
			"endDate": "2019-01-29T00:00:00.000Z",
			"price": 13
		}],
		"id": "5a5e0fba0a99dbc227a96933",
		"size": 13,
		"listPrice": 13,
		"deposit": 0
	}],
	"plans": [{
		"steps": [{
			"startDate": "2018-01-30T00:00:00.000Z",
			"endDate": "2019-01-29T00:00:00.000Z",
			"price": 250
		}],
		"id": "5a55ca64e29b41890a402653",
		"listPrice": 250,
		"price": 250,
		"deposit": 200,
		"count": 1
	}],
	"properties": {},
	"number": "CON-15",
	"team": "5a13f0437bab08ac23b269d5",
	"member": "5a13f0437bab08ac23b269d6",
	"status": "not_signed"
}

HTTP status code 200

Body

Type: application/json

Example:

[{
	"resourcesTotal": 156.25,
	"servicesTotal": 3004.7999999999997,
	"baseTotal": 3161.0499999999997,
	"total": 3793.2599999999993,
	"_id": "5a707fce37daead01decb3f1",
	"startDate": "2018-01-30T00:00:00.000Z",
	"endDate": "2019-01-29T00:00:00.000Z",
	"office": "5a13f0437bab08ac23b269d4",
	"number": "CON-15",
	"team": "5a13f0437bab08ac23b269d5",
	"member": "5a13f0437bab08ac23b269d6",
	"documentType": "licenseAgreement",
	"organization": "5a13f0437bab08ac23b269d3",
	"createdAt": "2018-01-30T14:23:10.846Z",
	"createdBy": "5a13ef3424a4d396232bb4eb",
	"plans": [{
		"id": "5a55ca64e29b41890a402653",
		"listPrice": 250,
		"price": 250,
		"deposit": 200,
		"count": 1,
		"steps": [{
			"startDate": "2018-01-30T00:00:00.000Z",
			"endDate": "2019-01-29T00:00:00.000Z",
			"price": 250
		}]
	}],
	"resources": [{
		"id": "5a5e0fba0a99dbc227a96933",
		"size": 13,
		"listPrice": 13,
		"deposit": 0,
		"steps": [{
			"startDate": "2018-01-30T00:00:00.000Z",
			"endDate": "2019-01-29T00:00:00.000Z",
			"price": 13
		}]
	}],
	"notice": {
		"months": 3
	},
	"type": "new",
	"status": "not_signed"
}]
delete

You can delete contracts by passing array of IDs to be deleted as request body.

Body

Type: application/json

Example:

["58c68b2c302d898ad348fde3", "58c45aa1261dd205c275bc78"]

/contracts/{contractId}

Retrieve a single contract.

get

Get the contract with id = {contractId}

URI Parameters

  • contractId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "58c45aa1261dd205c275bc78",
  "team": "58736fbda872255b08624f40",
  "office": "5873945c3ad3dd0e101ffa04",
  "startDate": "2017-03-11T00:00:00.000Z",
  "renewalDate": "2018-03-11T00:00:00.000Z",
  "number": "CON-MNCHSTR-1",
  "plans": [],
  "resources": [
    {
      "id": "5873960d3ad3dd0e101ffa3b",
      "listPrice": 500,
      "price": 300
    }
  ],
  "memberships": [
    "58c45aa4261dd205c275bc7b"
  ],
  "notice": {
    "months": 3
  },
  "status": "signed"
}

HTTP status code 404

Body

Type: application/json

Example:

{ "message": "Contract could not be found" }

Leads

Lead objects allow you to keep your enquiries and potential customers data in single place, add their contact details, add data about the services they are interested at, the deal size and the status of the conversation. The API allows you to create, delete, and update your lead records. You can retrieve individual lead as well as a list of all your leads or filter them by status.

/leads

get

Retrieve all leads.

Query Parameters

  • contact: (string)

    Filter by member id.

  • status: (one of open, won, lost)

    Filter by lead status. Convenient if you need list all open leads.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "contact": "565748274a955c790d808c77",
  "status": "open",
  "dealSize": 1200
}]
post

Add new lead. You can also add the contact inline.

Body

Type: application/json

Example:

[{
  "contact": {
    "name": "John Doe",
    "email": "john@doe.com",
    "team": "565748274a955c790d808c77",
    "phone": "+442130172",
    "team": {
      "name": "OfficeR&D",
      "email": "info@officernd.com",
      "properties": {
        "description": "Coworking management platform for prosperous communities and efficient workspaces"
      }
    }
  },
  "status": "open",
  "dealSize": 1200
}]

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "contact": "565748274a955c790d808c77",
  "status": "open",
  "dealSize": 1200
}]
delete

You can delete leads by passing array of IDs to be deleted as request body.

Body

Type: application/json

Example:

["57a1a8d8c334490c73b2856f"]

Visits

Collection of the visits in the organization

/visits

get

Lists visits in the organization. You can add "$populate=visitor" in the query string to populate visitor data along with the visit data.

Query Parameters

  • start.$gt: (date)

    All items starting after the pointed date

  • start.$lt: (date)

    All items starting before the pointed date

  • end.$gt: (date)

    All items ending after the pointed date

  • end.$lt: (date)

    All items ending before the pointed date

  • $populate: (string)

    Comma-separated list of all properties to be populated. Only id references can be populated. Refer to Populating queries section for more information.

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "57a1a8d8c334490c73b2856f",
  "office": "565748274a955c790d808c77",
  "visitor": {
      "_id": "57a1a88ac334490c73b2856d",
      "email": "miron@officernd.com",
      "name": "Miroslav Nedialkov",
      "team": "56535edb3492382393f68e5d",
      "actualImage": "//www.gravatar.com/avatar/d3c6debc20d468778003389094eaeb18?s=263&d=mm"
  },
  "team": "56535edb3492382393f68e5d",
  "member": "5798cf377200d6a001f84b3d",
  "end": "2016-08-03T11:18:22.732Z",
  "start": "2016-08-03T10:18:22.732Z"
}]

/visits/{visitId}

get

Gets a single visit by visitId. You can add "$populate=visitor" in the query string to populate visitor data along with the visit data.

URI Parameters

  • visitId: required (string)

    The Id of the corresponding visit

Query Parameters

  • $populate: (string)

    Comma-separated list of all properties to be populated. Only id references can be populated. Refer to Populating queries section for more information.

HTTP status code 200

Body

Type: application/json

Example:

{
  "_id": "57a1a8d8c334490c73b2856f",
  "office": "565748274a955c790d808c77",
  "visitor": {
      "_id": "57a1a88ac334490c73b2856d",
      "email": "miron@officernd.com",
      "name": "Miroslav Nedialkov",
      "team": "56535edb3492382393f68e5d",
      "actualImage": "//www.gravatar.com/avatar/d3c6debc20d468778003389094eaeb18?s=263&d=mm"
  },
  "member": "5798cf377200d6a001f84b3d",
  "team": "56535edb3492382393f68e5d",
  "end": "2016-08-03T11:18:22.732Z",
  "start": "2016-08-03T10:18:22.732Z"
}

Payments

Payment objects describe invoices, credit notes (credit memos), charges and credit allocations. They might contain information about any external links the invoice has.

You can retrieve individual invoices/credit notes as well as query all the items.

Here is the list of all properties the payment object has:

Payment

PropertyTypeRequiredDescription
numberstringtrueThe document number for the invoice / credit memo.
documentTypeenumfalseThe type of the document. It could be either invoice or creditNote. If ommited, invoice is assumed.
datedatetrueThe issue date of the document.
dueDatedatetrueThe due date of the document.
teamidfalseA reference to the company the invoice is issued for.
memberidfalseA reference to the member or individual the invoice is issued for.
officeidtrueA reference to the location the invoiced is issued by.
referencestringfalseAdditional data describing the invoice. It could be any string value.
taxTypeenumtrueThe type of the tax calculation for the invoice. It could be excluded, included or noTax.
allocationsarraytrueA lost of credit allocations. Each allocation has amount and target.
invoiceLinesarraytrueA lost of invoice line items.
vatAmountsarraytrueA lost of invoice vat amounts.
subtotalnumbertrueThe total of the invoice / credit note before tax.
amountnumbertrueThe total of the invoice / credit note after tax and discount.
payableAmountnumbertrueTotal amount due for this invoice. Voided and paid invoices has payableAmount of 0.

Credit Allocation

PropertyTypeRequiredDescription
targetidtrueIf payment is an invoice, a reference to the credit note, sourcing the creidt. If payment is a credit note, a reference to the invoice the credit is allocated to.
amountnumbertrueThe allocated amount.

Line Item

PropertyTypeRequiredDescription
descriptionstringtrueDescription of the line item.
accountidtrueA reference to the account the line item is allocated to.
vatPercentnumbertrueThe tax percent applied to the line item.
vatAmountnumbertrueThe tax amount applied to the line item.
quantitynumbertrueThe quantity of items described by the line item.
unitPricenumbertrueThe unit price as described in the system.
discountAmountnumbertrueThe calculated discount amount based on the discount set in the invoice.
baseUnitPricenumbertrueThe calculated unit price without tax.
baseTotalnumbertrueThe total wihtout tax.
totalnumbertrueThe total for the line item (including tax).

Vat Amount

PropertyTypeRequiredDescription
percentnumbertrueThe tax percent for the group.
totalnumbertrueThe tax total for the group.
taxRateidtrueA reference to the taxRate the group is for.

/payments

get

Retrieve all payment objects (invoices / credit notes)

Query Parameters

  • member: (string)

    Filter by member id

  • team: (string)

    Filter by team id

  • office: (string)

    Filter by office id.

  • $populate: (string)

    Comma-separated list of all properties to be populated. Only id references can be populated. Refer to Populating queries section for more information.

HTTP status code 200

Body

Type: application/json

Example:

[{
    "_id": "59a43cfbefd2661700e9f744",
    "number": "INV-14",
    "team": "565362e03492382393f68e71",
    "member": null,
    "office": "565748274a955c790d808c77",
    "date": "2017-08-28T00:00:00.000Z",
    "dueDate": "2017-09-01T00:00:00.000Z",
    "reference": "September Invoice",
    "taxType": "excluded",
    "allocations": [{
        "amount": 100,
        "target": "59a43d1aefd2661700e9f76c"
    }],
    "subtotal": 250,
    "discountAmount": 0,
    "vatAmounts": [{
        "percent": 20,
        "taxRate": "57d6b754871bb8bdb46a7e67",
        "total": 50
    }],
    "amount": 300,
    "paidAmount": 200,
    "allocatedAmount": 100,
    "pendingAmount": 0,
    "payableAmount": 0,
    "status": "paid",
    "invoiceLines": [{
        "description": "Dedicated Desk, $250.00, Sep 1, 2017 - Sep 30, 2017",
        "discount": 0,
        "account": "57b1d525462a54e463af70ec",
        "vatPercent": 20,
        "taxRate": "57d6b754871bb8bdb46a7e67",
        "plan": "56535f483492382393f68e5e",
        "unitPrice": 250,
        "baseUnitPrice": 250,
        "quantity": 1,
        "discountAmount": 0,
        "subtotal": 250,
        "baseTotal": 250,
        "vatAmount": 50,
        "total": 300
    }]
}]

/payments/{paymentId}

Retrieve an individual invoice or credit note.

get

Get the invoice / credit note with id = {paymentId}

URI Parameters

  • paymentId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

{
    "_id": "59a43d1aefd2661700e9f76c",
    "number": "INV-15",
    "team": "565362e03492382393f68e71",
    "member": null,
    "office": "565748274a955c790d808c77",
    "date": "2017-08-28T00:00:00.000Z",
    "documentType": "creditNote",
    "taxType": "excluded",
    "allocations": [{
        "amount": 100,
        "target": "59a43cfbefd2661700e9f744"
    }],
    "subtotal": 83.33,
    "vatAmounts": [{
        "percent": 20,
        "taxRate": "57d6b754871bb8bdb46a7e67",
        "total": 16.67
    }],
    "amount": 100,
    "discountAmount": 0,
    "discount": 0,
    "paidAmount": 0,
    "allocatedAmount": 100,
    "pendingAmount": 0,
    "payableAmount": 0,
    "status": "paid",
    "invoiceLines": [{
        "description": "Dedicated Desk, $250.00, Sep 1, 2017 - Sep 30, 2017",
        "account": "57b1d525462a54e463af70ec",
        "vatPercent": 20,
        "taxRate": "57d6b754871bb8bdb46a7e67",
        "plan": "56535f483492382393f68e5e",
        "quantity": 0.3333,
        "unitPrice": 250,
        "discountAmount": 0,
        "baseUnitPrice": 250,
        "vatAmount": 16.67,
        "subtotal": 83.33,
        "baseTotal": 83.33,
        "total": 100
    }]
}

HTTP status code 404

Body

Type: application/json

Example:

{ "message": "Payment not found" }

/payments/{paymentId}/charges

All charges for a specified invoice/credit note. Please check the Charges endpoint for more details.

get

Get all charges for a specific invoice.

URI Parameters

  • paymentId: required (string)

HTTP status code 200

Body

Type: application/json

Example:

[{
  "_id": "59a43c4d99852e1500f519d2",
  "date": "2017-08-28T15:52:46.890Z",
  "reference": "**** **** **** 4242 (Visa)",
  "account": "Stripe Card",
  "amount": 250,
  "status": "success",
  "source": "OfficeR&D",
  "integration": {
    "providerChargeId": "ch_1AvpXeEPo4o6pr4dASH0ElEF"
  }
}]
post

Create a new charge for the specified invoice. All required fields must be specified.

URI Parameters

  • paymentId: required (string)

Body

Type: application/json

Example:

{
  "date": "2017-08-28T15:52:46.890Z",
  "reference": "**** **** **** 4242 (Visa)",
  "account": "Stripe Card",
  "amount": 50,
  "status": "success",
  "source": "ERP"
}

HTTP status code 400

Body

Type: application/json

Example:

{
  "name": "InvalidOperationError",
  "message": "Invalid amount provided.",
  "type": "Invalid operation"
}

Charges

Charge object describes a single payment associated with an invoice. Charges can be either created manually, or done via a payment gateway.

Here is the structure of the charge object

Charge

PropertyTypeRequiredDescription
amountnumbertrueThe amount of the transaction.
datedatetrueThe exact date of the transaction.
statusenumtrueThe status of the transaction. One of the following success, pending, fail.
referencestringtrueHuman readable description of the transaction.
sourcestringfalseThe system the charge originated at. OfficeR&D by default
accountstringfalseThe name of the account where money are depositet at.
integrationobjectfalsePresent if charge is collected via payment gateway. Its property providerChargeId is set to the gateway charge ID
createdAtdatereadonlyThe date when the charge has been created at.
createdByidreadonlyThe user that created the charge.
paymentidreadonlyThe invoice or credit note the charge is associated with.

/charges

get

Retrieve all charge objects.

Query Parameters

  • createdAt.$gt: (date)

    All items created after the pointed date

  • createdAt.$lt: (date)

    All items created before the pointed date

  • payment: (string)

    Filter by parent invoice. Similar to /payments/{paymentId}/charges.

  • status: (one of success, pending, fail)

    Filter charges by their status. Usually you would need only the successful charges.

Network

API to help network modules integrate with OfficeR&D

/network/auth

post

Use this endpoint to authorize a new device for a member.

Body

Type: application/json

Schema:

{
    "$schema": "http://json-schema.org/draft-03/schema",
    "required": true,
    "type": "object",
    "properties": {
        "username": {
            "description": "the email address of the member",
            "type": "string"
        },
        "password": {
            "description": "The clear text password of the member",
            "type": "string"
        },
        "macAddress": {
            "description": "The mac address of the new device to be registered",
            "type": "string"
        },
        "source": {
            "description": "The name of the module that is requesting authorization",
            "type": "string"
        }
    },
    "required": ["username", "password", "macAddress"]
}

Example:

{
  "username": "john.doe@gmail.com",
  "password": "johndoe",
  "macAddress": "01-23-45-67-89-ab",
  "source": "OfficeR&D network module"
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "macAddress": "01-23-45-67-89-ab",
  "source": "OfficeR&D network module"
}

HTTP status code 403

Body

Type: application/json

Example:

{
  "message": "Not a member"
}

/network/checkin

post

Use this endpoint to checkin a member by their mac address.

Body

Type: application/json

Schema:

{
    "$schema": "http://json-schema.org/draft-03/schema",
    "required": true,
    "type": "object",
    "properties": {
        "macAddress": {
            "description": "The mac address of the device that logged to the network.",
            "type": "string"
        },
        "office": {
            "description": "The ID of the OfficeR&D location where the member devide logged in. If not specified no location is associated with the checkin.",
            "type": "string"
        },
        "date": {
            "description": "When the member device logged in. If not specified now is assumed.",
            "type": "string"
        }
    },
    "required": ["macAddress"]
}

Example:

{
  "macAddress": "01-23-45-67-89-ab",
  "office": "565748274a955c790d808c77"
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "office": "565748274a955c790d808c77",
  "devices": ["01-23-45-67-89-ab"]
}

HTTP status code 403

Body

Type: application/json

Example:

{
  "message": "Not a member"
}

/network/checkout

post

Use this endpoint to checkout a member by their mac address.

Body

Type: application/json

Schema:

{
    "$schema": "http://json-schema.org/draft-03/schema",
    "required": true,
    "type": "object",
    "properties": {
        "macAddress": {
            "description": "The mac address of the device that logged out from the network.",
            "type": "string"
        },
        "date": {
            "description": "When the member device logged out. If not specified now is assumed.",
            "type": "string"
        }
    },
    "required": ["macAddress"]
}

Example:

{
  "macAddress": "01-23-45-67-89-ab"
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "office": "565748274a955c790d808c77",
  "devices": ["01-23-45-67-89-ab"]
}

HTTP status code 403

Body

Type: application/json

Example:

{
  "message": "Member is not checked in"
}

Authentication

/auth/signin

post

Authenticate member by email & password. Returns the access token to login (impersonate) as a member.

Body

Type: application/json

Example:

{
  "username": "miron@officernd.com",
  "password": "pa$$word"
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU4YTMwYmU5NGVhNjhlZTZjMzk0ZGUzMSIsImlhdCI6MTQ4NzA4MTE4NCwiZXhwIjoxNTE4NjE3MTg0fQ.6wjmGAEqojB7Uc473SNCIFIxQgJv_GusgK2w64oDW-I"
}

HTTP status code 404

Body

Type: application/json

Example:

{
  "message": "Unauthorized"
}

/auth/member

post

Authenticate member by given email. Returns the access token to login (impersonate) as a member.

The authentication token returned by this endpoint can be used to generate quick login links to the members portal. You just need to add access_token=<token> to the URL.

Example:

  https://icowork.officernd.com/calendar?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU4NDZmMjhhZmY1ZDg4MTI2YWJjZmMzZiIsImlhdCI6MTQ4MTExNjQwOCwiZXhwIjoxNDgxMjg5MjA4fQ.ElceBwjTRBhu669SWkn_Za8VKk-cwomzmbEsNywPt5A

Body

Type: application/json

Example:

{
  "email": "info@officernd.com"
}

HTTP status code 200

Body

Type: application/json

Example:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU4NDZmMjhhZmY1ZDg4MTI2YWJjZmMzZiIsImlhdCI6MTQ4MTExNjQwOCwiZXhwIjoxNDgxMjg5MjA4fQ.ElceBwjTRBhu669SWkn_Za8VKk-cwomzmbEsNywPt5A"
}

HTTP status code 404

Body

Type: application/json

Example:

{
  "message": "Member with such an email could not be found"
}

Reports

/reports/occupancy

This set of reports provides aggregated data regarding the resources and members of the space. As this data is related to a specific time frame, these APIs allow quering data for different time ranges and divided by different time periods.

To set this time filter set the following query string parameters:

  • from - start date of the period in ISO date format (i.e. 2017-10-01)
  • to - end date of the period in ISO date format (i.e. 2017-11-31)
  • interval - length of the time period the report is divided by (one of 'day', 'week', 'month')

/reports/occupancy/by-customer

get

Generates a report for each customer, containing information about the resource the customer is using in the space in the specified time period.

If not grouped, the report is an array of type By Customer Occupancy Stats. If grouped by office or floor, the result is an array of type Grouped By Customer Occupancy Stats.

By Customer Occupancy Stats

PropertyTypeDescription
teamobjectThe _id and name of the company the report entry is for (i.e. the group key).
memberobjectThe _id and name of the company the report entry is for (i.e. the group key).
stats[object]List of the report data divided by intervals. The value of this field is of type Customer Occupancy Stats.

Customer Occupancy Stats

PropertyTypeDescription
datedateThe start date of the interval the stats are about (i.e. the subgroup key).
totalobjectThe sum of all occupied resource used by the customer. The value of this field is of type Resource Type Stats.
* (resource type)objectThe count of resources used by the customer. The value of this field is of type Resource Type Stats. The name of the field could be one of desk, hotdesk, team_room, or any other resource type.

Resource Type Stats

PropertyTypeDescription
countnumberThe count of resources of the specified type being used by the customer.
unitsnumberThe total units count of the specified type being used by the customer. This property is missing for single resources like desks and contain the count of the sub resources for resources like private offices.

Grouped By Customer Occupancy Stats

PropertyTypeDescription
roomIDReference to the floorplan this group is for. Only present when grouped by room.
officeIDReference to the location this group is for. Only present when grouped by office.
byCustomer[object]The byCustomer report for the specified group. The value of this field is an array of type By Customer Occupancy Stats.

Query Parameters

  • $group: (string)

    Property to group the list by (one of room, office). Default is null (i.e. no grouping)

  • office: (string)

    Filter by office id.

  • from: (date)

    Start of the period for reporting. Default is today.

  • to: (date)

    End of the period for reporting. Default is today.

  • interval: (string)

    Interval length to split the report (one of day, week, month). Default is day.

HTTP status code 200

Body

Type: application/json

Example:

[{
    "team": {
        "_id": "56535edb3492382393f68e5d",
        "name": "OfficeR&D"
    },
    "stats": [{
        "date": "2017-05-01T00:00:00.000Z",
        "team_room": {
            "count": 1,
            "units": 4
        },
        "total": {
            "count": 1,
            "units": 4
        }
    }, {
        "date": "2017-06-01T00:00:00.000Z",
        "team_room": {
            "count": 1,
            "units": 4
        },
        "total": {
            "count": 1,
            "units": 4
        }
    }]
}, {
    "team": {
        "_id": "565362e03492382393f68e71",
        "name": "PiLabs"
    },
    "stats": [{
        "date": "2017-05-01T00:00:00.000Z",
        "desk": {
            "count": 1
        },
        "total": {
            "count": 1,
            "units": 1
        }
    }, {
        "date": "2017-06-01T00:00:00.000Z",
        "desk": {
            "count": 1
        },
        "total": {
            "count": 1,
            "units": 1
        }
    }]
}]

/reports/occupancy/assignable-stats

get

Generates report containing occupancy statistics for all resource types, divided by periods as specified by the time period filter.

If not grouped, the report is an array of type Interval Occupancy Stats.

Interval Occupancy Stats

PropertyTypeDescription
datedateThe start date of the interval the stats are about (i.e. the group key).
totalobjectThe sum/avg of occupancy stats for all resource types. The value of this field is of type Occupancy Stats.
* (resource type)objectThe occpancy stats for each resource type. The value of this field is of type Extended Occupancy Stats.

Occupancy Stats

PropertyTypeDescription
countnumberThe count of the specified resource type.
unitsnumberThe total units count of the specified type. This property is missing for single resources like desks and contain the count of the sub resources for resources like private offices.
occupiednumberThe count of the occupied units of the specified resource type. For single resources this is the count of the resources occupied.
occupancynumberThe occupancy rate for the specified resource type calculated based on units (i.e. occupied / units). For single resources this is the based on the resources count instead.

Extended Occupancy Stats

All properties from Occupancy Stats plus

PropertyTypeDescription
statuses[object]Resources count grouped by their status. The value of each item is of type Status Group Stats.

Status Group Stats

PropertyTypeDescription
statusstringThe status of the group.
countnumberThe count of resources of the specified type and status for the specific date.
unitsnumberThe total units count of the specified type and status for the specific date.

If the report is grouped (i.e. the $group query string parameter is passed), the report is an array of type Group Occupancy Stats.

Group Occupancy Stats

PropertyTypeDescription
roomIDReference to the floorplan this group is for. Only present when grouped by room.
officeIDReference to the location this group is for. Only present when grouped by office.
statsobjectThe stats for the specified group. The value of this field is an array of type Interval Occupancy Stats.

Query Parameters

  • office: (string)

    Filter by office id.

  • $group: (string)

    Property to group the list by (one of room, office). Default is null (i.e. no grouping)

  • from: (date)

    Start of the period for reporting. Default is today.

  • to: (date)

    End of the period for reporting. Default is today.

  • interval: (string)

    Interval length to split the report (one of day, week, month). Default is day.

HTTP status code 200

Body

Type: application/json

Example:

[{
    "date": "2017-05-01T00:00:00.000Z",
    "total": {
        "count": 69,
        "occupied": 22,
        "occupancy": 0.29,
        "units": 76
    },
    "desk": {
        "statuses": [{
                "status": "available",
                "count": 16,
                "units": 16
            },
            {
                "status": "occupied",
                "count": 18,
                "units": 18
            },
            {
                "status": "reserved",
                "count": 6,
                "units": 6
            }
        ],
        "count": 40,
        "occupied": 18,
        "occupancy": 0.45
    },
    "hotdesk": {
        "statuses": [{
            "status": "hotdesk",
            "count": 16,
            "units": 16
        }],
        "count": 16,
        "occupied": 0,
        "occupancy": 0
    },
    "desk_tr": {
        "statuses": [{
                "status": "available",
                "count": 5,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 3,
                "units": 3
            },
            {
                "status": "reserved",
                "count": 2,
                "units": 2
            }
        ],
        "count": 10,
        "occupied": 0,
        "occupancy": 0
    },
    "team_room": {
        "statuses": [{
                "status": "available",
                "count": 1,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 1,
                "units": 4
            },
            {
                "status": "reserved",
                "count": 1,
                "units": 1
            }
        ],
        "count": 3,
        "occupied": 4,
        "occupancy": 0.4,
        "units": 10
    }
}, {
    "date": "2017-06-01T00:00:00.000Z",
    "total": {
        "count": 69,
        "occupied": 23,
        "occupancy": 0.3,
        "units": 76
    },
    "desk": {
        "statuses": [{
                "status": "available",
                "count": 17,
                "units": 17
            },
            {
                "status": "available_soon",
                "count": 1,
                "units": 1
            },
            {
                "status": "occupied",
                "count": 17,
                "units": 17
            },
            {
                "status": "reserved",
                "count": 5,
                "units": 5
            }
        ],
        "count": 40,
        "occupied": 18,
        "occupancy": 0.45
    },
    "hotdesk": {
        "statuses": [{
            "status": "hotdesk",
            "count": 16,
            "units": 16
        }],
        "count": 16,
        "occupied": 0,
        "occupancy": 0
    },
    "desk_tr": {
        "statuses": [{
                "status": "available",
                "count": 5,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 4,
                "units": 4
            },
            {
                "status": "reserved",
                "count": 1,
                "units": 1
            }
        ],
        "count": 10,
        "occupied": 0,
        "occupancy": 0
    },
    "team_room": {
        "statuses": [{
                "status": "available",
                "count": 1,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 2,
                "units": 5
            }
        ],
        "count": 3,
        "occupied": 5,
        "occupancy": 0.5,
        "units": 10
    }
}, {
    "date": "2017-07-01T00:00:00.000Z",
    "total": {
        "count": 69,
        "occupied": 25,
        "occupancy": 0.33,
        "units": 76
    },
    "desk": {
        "statuses": [{
                "status": "available",
                "count": 21,
                "units": 21
            },
            {
                "status": "occupied",
                "count": 19,
                "units": 19
            }
        ],
        "count": 40,
        "occupied": 19,
        "occupancy": 0.48
    },
    "hotdesk": {
        "statuses": [{
            "status": "hotdesk",
            "count": 16,
            "units": 16
        }],
        "count": 16,
        "occupied": 0,
        "occupancy": 0
    },
    "desk_tr": {
        "statuses": [{
                "status": "available",
                "count": 5,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 5,
                "units": 5
            }
        ],
        "count": 10,
        "occupied": 1,
        "occupancy": 0.1
    },
    "team_room": {
        "statuses": [{
                "status": "available",
                "count": 1,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 2,
                "units": 5
            }
        ],
        "count": 3,
        "occupied": 5,
        "occupancy": 0.5,
        "units": 10
    }
}, {
    "date": "2017-08-01T00:00:00.000Z",
    "total": {
        "count": 69,
        "occupied": 25,
        "occupancy": 0.33,
        "units": 76
    },
    "desk": {
        "statuses": [{
                "status": "available",
                "count": 21,
                "units": 21
            },
            {
                "status": "occupied",
                "count": 19,
                "units": 19
            }
        ],
        "count": 40,
        "occupied": 19,
        "occupancy": 0.48
    },
    "hotdesk": {
        "statuses": [{
            "status": "hotdesk",
            "count": 16,
            "units": 16
        }],
        "count": 16,
        "occupied": 0,
        "occupancy": 0
    },
    "desk_tr": {
        "statuses": [{
                "status": "available",
                "count": 5,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 5,
                "units": 5
            }
        ],
        "count": 10,
        "occupied": 1,
        "occupancy": 0.1
    },
    "team_room": {
        "statuses": [{
                "status": "available",
                "count": 1,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 2,
                "units": 5
            }
        ],
        "count": 3,
        "occupied": 5,
        "occupancy": 0.5,
        "units": 10
    }
}, {
    "date": "2017-09-01T00:00:00.000Z",
    "total": {
        "count": 69,
        "occupied": 25,
        "occupancy": 0.33,
        "units": 76
    },
    "desk": {
        "statuses": [{
                "status": "available",
                "count": 21,
                "units": 21
            },
            {
                "status": "occupied",
                "count": 19,
                "units": 19
            }
        ],
        "count": 40,
        "occupied": 19,
        "occupancy": 0.48
    },
    "hotdesk": {
        "statuses": [{
            "status": "hotdesk",
            "count": 16,
            "units": 16
        }],
        "count": 16,
        "occupied": 0,
        "occupancy": 0
    },
    "desk_tr": {
        "statuses": [{
                "status": "available",
                "count": 5,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 5,
                "units": 5
            }
        ],
        "count": 10,
        "occupied": 1,
        "occupancy": 0.1
    },
    "team_room": {
        "statuses": [{
                "status": "available",
                "count": 1,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 2,
                "units": 5
            }
        ],
        "count": 3,
        "occupied": 5,
        "occupancy": 0.5,
        "units": 10
    }
}, {
    "date": "2017-10-01T00:00:00.000Z",
    "total": {
        "count": 69,
        "occupied": 25,
        "occupancy": 0.33,
        "units": 76
    },
    "desk": {
        "statuses": [{
                "status": "available",
                "count": 21,
                "units": 21
            },
            {
                "status": "occupied",
                "count": 19,
                "units": 19
            }
        ],
        "count": 40,
        "occupied": 19,
        "occupancy": 0.48
    },
    "hotdesk": {
        "statuses": [{
            "status": "hotdesk",
            "count": 16,
            "units": 16
        }],
        "count": 16,
        "occupied": 0,
        "occupancy": 0
    },
    "desk_tr": {
        "statuses": [{
                "status": "available",
                "count": 5,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 5,
                "units": 5
            }
        ],
        "count": 10,
        "occupied": 1,
        "occupancy": 0.1
    },
    "team_room": {
        "statuses": [{
                "status": "available",
                "count": 1,
                "units": 5
            },
            {
                "status": "occupied",
                "count": 2,
                "units": 5
            }
        ],
        "count": 3,
        "occupied": 5,
        "occupancy": 0.5,
        "units": 10
    }
}]

Checkout

Checkout and checkout summary endpoints allow you to create a new order or get the preview of an order. Depending on the organization settings and the current member status they may create an invoice, charge the member and send an invoice automatically.

Here is the list of all properties the checkout request object has:

Checkout Request

PropertyTypeRequiredDescription
plans[PlanRequest]falseA list of plan request definitions to be added to the order.
fees[FeeRequest]falseA list of fee request definitions to be added to the order.
discountCodes[string]false0 or 1 discount codes to be applied.

Plan Request

PropertyTypeRequiredDescription
planidtrueThe ID of the membership plan to be ordered.
startDatedatetrueThe start date of the ordered membership.
endDatedatefalseThe end date of the ordered membership.

Fee Request

PropertyTypeRequiredDescription
planidtrueThe ID of the membership plan to be ordered.
datedatetrueThe date the one-off is ordered for.

/checkout

post

Create a new membership

Body

Type: application/json

Example:

{
    "plans": [{
        "plan": "5aa14137890301e40c912ce5",
        "addOns": [],
        "startDate": "2018-04-20T00:00:00.000Z"
    }],
    "fees": [],
    "discountCodes": [ "10percent" ]
}

HTTP status code 200

/checkout/summary

post

Get a checkout summary.

Body

Type: application/json

Example:

{
    "plans": [{
        "plan": "5aa14137890301e40c912ce5",
        "addOns": [],
        "startDate": "2018-04-20T00:00:00.000Z"
    }],
    "fees": [],
    "discountCodes": [ "10percent" ]
}

HTTP status code 200

Body

Type: application/json

Example:

{
    "stats": {
        "taxType": "included",
        "invoiceLines": [
            {
                "description": "Hotdesk plan, £250.00, Apr 20, 2018 - May 18, 2018 (prorated 29 days)",
                "discount": 10,
                "account": "5aa138f97adac0140057ad0d",
                "vatPercent": 0,
                "taxRate": "5aa138f97adac0140057ad13",
                "plan": "5aa14137890301e40c912ce5",
                "membership": "5addc9b4548cb55832f8ef34",
                "quantity": 0.9534,
                "unitPrice": 250,
                "price": 238.35,
                "discountAmount": 23.84,
                "baseUnitPrice": 250,
                "vatAmount": 0,
                "subtotal": 214.52,
                "baseTotal": 214.52,
                "total": 214.52
            }
        ],
        "discount": 23.84,
        "baseTotal": 214.52,
        "subtotal": 214.52,
        "vatAmounts": [],
        "total": 214.52,
        "payableAmount": 214.52
    },
    "billingFlow": {
        "filter": {
            "status": "active"
        },
        "options": {
            "invoiceImmediatelly": false,
            "requireCreditCard": false,
            "chargeImmediatelly": false,
            "sendInvoice": false
        }
    }
}

Hosted Payment Gateway

OfficeR&D Hosted Payment Gateway extensibility allows for Developers to implement payment gateway integration that is not provided out-of-the-box.

Configure your hosted payment gateway

To start developing and testing your hosted payment gateway, enable and configure it inside the OfficeR&D admin console, following these steps:

  1. Login to the OfficeR&D admin console as an Owner and navigate to Settings > Integartions.
  2. Locate the Hosted Payment Gateway under the Payment Gateways section.
  3. Click the Activate link and then Configure

A dialog is shown that allows you to input and get all necessary information for the integration to work.

  • The Name field is used to define the name of the integration. If you input Cool Payments, the customer will see that as Pay with Cool Payments
  • The Secret field is read-only. Its value is initially hidden and you can retrieve it by hitting the "eye" button next to it. You must use the value of this field to verify requests and sign your responses. This secret should be used only on your servers and should never be shown, served or shared with the end user.
  • The Gateway URL should be a fully formed url i.e. - https://your.integration.url/path. You can put parameter placeholders that will be populated when OfficeR&D initiates the customer redirect request. The placeholders that you can use are as follows: {{ amount }}, {{ reference }}, {{ transactionId }}, {{ signature }}, {{ redirectUrl }}.
    • Example: https://pay.cool-payments.com/hosted?amount={{ amount }}&ref={{ reference }}&tId={{ transactionId }}&signature={{ signature }}&redirectUrl={{ redirectUrl }}

How it works

  1. The customer chooses to pay with the hosted payment gateway, configured in OfficeR&D.
  2. OfficeR&D redirects the customer to your gateway's URL, submitting the correct Request parameters. Your gateway must verify the signature parameter value and present a hosted payments page to the customer.
  3. The customer payment is processed on the hosted payment page that you provide.
  4. Upon completing the payment, customers should be redirected back to the redirectUrl with all required Response parameters in the query string. This includes the signature. If the payment was successful, the status parameter should have a success value. Otherwise the status should be - fail.
  5. OfficeR&D accounts for the payment to the respective invoice and shows a success or failure message the customer.

Developing your hosted payment gateway integration

OfficeR&D enables you to extend the system so that you can process payments using a custom-developed payment page. OfficeR&D checkout will redirect the customer to the configured payment gateway page. The page should be able to handle predefined request parameter values. After the customers complete the payment, they will be redirected back to OfficeR&D, with predefined response parameter values.

It is the responsibility of the payment gateway to build the page that handles the payment requests.

Request and Response signing mechanism

All requests and responses must be signed and verified using HMAC-SHA256. The signing should use the following rules:

  • For key you must use the value if the Secret field defined in your integration configuration page.

  • The value of message must be a string comprised of the values of all key parameters concatenated by the pipe symbol ('|') as a separator.

    • The key parameters for the request are amount, reference and transactionId.

      Example: If the request amount is 12.34, it has a reference INV-001 and a transactionId - 6f47c19b-eb9d-4ee5-a144-19f7b9263183, then the message should be the following string:

      12.34|INV-001|6f47c19b-eb9d-4ee5-a144-19f7b9263183

    • The key parameters for the response are status and transactionId.

      Example: If the response status is success and its transactionId is 6f47c19b-eb9d-4ee5-a144-19f7b9263183, then the message should be the following string:

`success|6f47c19b-eb9d-4ee5-a144-19f7b9263183`
  • Resulting codes must be hex-encoded and passed as value of signature parameter. Make sure to use case-insensitive comparison when verifying the provided signature values.

Assuming your HMAC key is "11111111-1111-1111-1111-111111111111", the signatures of the example messages should be:

  • 12.34|INV-001|6f47c19b-eb9d-4ee5-a144-19f7b9263183 - 617b0b7d29e57db460208904f0e64c11092872d86faf581598c3ba9b8b0e00ae
  • success|6f47c19b-eb9d-4ee5-a144-19f7b9263183 - 2c6d0e09f76011cebf9073a4fa08d752e5c5c440e750c6ee1f8ad5d5cce70bad

Request parameters

NameTypeRequiredDescription
amountnumbertrueThe amount that needs to be charged.
referencestringtrueA reference string that clarifies what the charge is for (i.e. INV-001).
transactionIdstringtrueA unique identifier that references the transaction.
signaturestringtrueA signature generated from the amount, reference and transactionId.
redirectUrlstringtrueA url to redirect back when charge is processed or canceled.

Response parameters

NameTypeRequiredDescription
statusstringtrueThe status of the transaction - values should be either success or fail.
transactionIdstringtrueThe unique identifier that was passed in the initial request.
signaturestringtrueA signature generated from the status and transactionId.
errorstringfalseAn error message with more details about the reason of the failure.