Introduction
The Building Engines Prism API allows programmatic access to our services. Here we will focus on some common elements of the API in general and Work Orders more specifically. We will also touch upon the core additional services such as Preventive Maintenance/Equipment, as well as Inspections, and other modules. This guide is intended to illustrate the overall approach and common patterns of the API allowing better understanding of the detailed, reference documentation.
Building Engines has developed the interface as a Secure, HTTP RESTful API. JSON formatting is used for both requests and responses. Traditional HTTP verbs are supported such as POST (creation), GET (for listing or retrieval), PUT (for whole object updating), PATCH (for partial object updating), and, in limited cases, DELETE (for object removal) are supported.
The API is authenticated by identifying the credentials of a given user. This user will be tracked as the current user for auditing purposes. Further, the API internally enforces a privilege scheme that may restrict some or all access depending on the authenticated user. These privileges are assigned by the administrator of the account by granting the user access to given groups of permissions such as Can Close Work Order or Can Reassign Work Order. This document describes the high-level concepts and flows facilitated through the Prism API. This is used in conjunction with detailed OpenAPI 2.0 (Swagger) documentation that is hosted at Prism API.
Any questions related to specifics from the reference documentation can be directed at your Building Engines API support contact.
URL
The Building Engines API utilizes HTTPS exclusively and is reached at:
https://api.connect.buildingengines.com
An active Building Engines Prism account is required for authentication. Contact support for more information or to request access for early Beta testing.
API Key
For production applications you must register with Building Engines for an API Key. This key authorizes your application to call into the Building Engines API. This is not the same as user authentication described below. This API key is used for any calls from the application in question.
An API Key appears as a random string, such as:
kyMWR8s9.ZEMvNubPAxWndkLatME3NokZxTZaSuYA
Such a key is sent with every API request as an HTTP header as in:
X-Prism-App: kyMWR8s9.ZEMvNubPAxWndkLatME3NokZxTZaSuYA
Failure to supply a correct API key can result in all calls returning an HTTP 401 authentication failure.
Core Concepts/Objects
Within the Building Engines API, one will see some common concepts used and reused . These include:
-
Account
- An Account represents a Building Engines customer and a collection of buildings and the associated organizations, management organizations, vendors, and tenants, that are related to those buildings. This may be thought of as a Portfolio.
-
Organization (Company)
- An Account contains multiple Organizations. Foremost of these is the Management Organization representing the Property Management Organization (PMO) responsible for one or more Buildings. Other Organization types include Vendors, contracted to work in the Building, Owners, monitoring operational efficiency, and, of course, Tenant Organizations residing in the Building.
- In more specific configurations, a Prism Account may allow for multiple PMO companies. In this configuration, the primary PMO company is designated as the PMO company created with the Account is created. Secondary PMO companies can then be added potentially with privileges to add Buildings under management, Vendor or Tenant companies, etc. The data scoping rules allow each secondary PMO to be isolated from each other with limited data sharing controlled by the primary PMO company.
-
Building
- A Building is the fundamental unit within Building Engines. It is to a Building that Work Orders are associated. A Building is considered managed by one PMO company, typically the Account-level PMO company. Buildings house Spaces which indicate locations in the Building including the most fundamental, Floor, as Suites occupied by Tenant companies and other spaces such as Common Areas.
Together these concepts can be visualized as follows:
Figure 1: Account, Organizations, and Building Relationships
These are, of course, just a subset of the concepts and objects in the Prism API but they will be involved in most requests so bear special note.
Common Headers
The following common headers are generally expected to be included:
HTTP Header | Description | Example/Value |
Accept | Describes expected data return format and specifies the API version required. | application/json;version=1.0 |
Content-Type | Describe the format of the body being sent when a body is applicable. For example, in POST/PUT/PATCH requests. | application/json |
Authorization | Specify the authorization token established by authenticating with the API /auth/login endpoint. See below in Authentication | Bearer eyj0eA4xQiL....Bns87a |
If the request does not include a body, no Content-Type is required. If the request is for authentication purposes (/auth/login and /auth/refresh), no Authorization token is needed. Generally, however, you will include the three headers above.
Pagination
Many Building Engines API requests return objects in pages to reduce the memory required of the result and increase performance. In these cases, the results will always take the form of a JSON object including the following fields:
- Count – the overall count of the result
- Next – Either null or a link to retrieve the next page of results
- Previous – Either null of a link to retrieve the previous page of results
- Results – An array of the result objects following the format of the specific request
The request can override the pagination by supplying URL arguments. They include limit to reset the page size from the default to the given value and offset to reset the record number to begin fetching at.
An example of the JSON result follows:
{
“count”: 172,
“next”: “https://api...buildingengines.com/work_orders?limit=10&offset=0”,
“prev”: null,
“results”: [{
“id”: “...”,
....
Pagination will also honor whatever additional filtering has been applied. Filtering options are described in the Building Engines API Reference for the GET call in question.
Included Content
Some objects, such as Work Orders, include additional details, such as Comments, Equipment records, or Attachments that may cause the resultant object to be larger than desired. In these cases, the API supports a URL parameter includes where a comma-separated list of such objects can be defined.
For example, GET /work_orders, will not return the full array of comment objects whereas GET /work_orders?include=comments *will* return a comments array in the result.
The API reference will document will indicate when included content exists. The ‘include’ parameter is only honored on GET (list) and GET <id> (retrieve) operations.
Error Returns
Typical requests will fail with a non-successful HTTP status code (e.g. 400 (Bad Request), 404 (Not Found)) and an optional, JSON encoded, body. The body will include a dictionary with field names as keys and a string or an array of error strings in the language sent in the Accept headers to the API.
For example, failed attempt to update an email address and password might result in a body such as the following:
{
“email”: [ “Not a valid email address” ],
“password”: [
“Password must include more than 8 characters”,
“Password must include a capital letter” ]
}
If errors are not related to a specific field, they will have the special dictionary tag of detail which would include a string or an array of error strings.
In some cases, rather than identifying a field, a validation error may occur related to the entire request. This may be represented as follows:
{
“non-field-error”: “Inspection must set one form of assignee.”
}
These responses may come in the form of a single string, or an array of strings and it is best to defensively code for either case.
Modules
The Building Engines API has common supporting elements, such as APIs for Building, Company, and User manipulation, and others requests specific to Modules, or subsets of functionality related to Commercial Real Estate (CRE) functions.
The modules currently detailed within the Prism SDK include:
- Work Orders – Reactive tasks
- Preventive Maintenance – Proactive support of Equipment
- Inspections – Periodic reviews or checklist-style processes
- Communications – Messaging system to building occupants or workers
- Visitors – Management of Visitors to building occupants
Common Features
Custom Fields
A feature of several object types in the system, including Buildings, Organizations, and Users, is the ability to extend the data model by including user-defined or custom fields. These fields have attributes such as a data type, a name, and can have values depending on different objects they are related to.
In this way if, for instance, a building has a special region and a certain kind of charge code, those can be represented as fields defined by the organization. These fields will appear in forms, API results, and should be selected in grids and in exports.
Also, futures for Custom Fields include types on tasks such as Work Orders and Equipment and allowing for fields for certain types of objects.
Types
At present, Prism limits the data type to “text” for a text string. In the future, the full list of types will include:
- “text” – a string, typically one line. Allowed to be blank or null, generally 80 characters or less.
- “textarea” – a string with potentially multiple lines. CR/LF honored for display purposes and text limits are higher (2000 characters). Also allowed to be blank or null.
- “bool” – JavaScript values of “true” or “false”
- “float” – A numeric floating-point value
- “int” – A numeric integer value.
- “currency” – A string tuple of a floating-point value and a currency as in “42.99 USD” or “1.00 EUR”.
- “url” – A string URL.
Some validation is performed as well. For a text field, a maximum length will be enforced and specialized types, such as URLs, are validated for correctness.
Reading (GET)
An object that includes custom fields, such as a Building, will return the fields as an array of JavaScript Object Notation (JSON) objects. The structure is:
- custom_fields (Array)
- Object
- id – GUID internal identifier of the value
- field_id – GUID identifier of the field this object represents § field_name – API name of the custom field
- value – Value of the object
- field – Object
- id – GUID of the field
- name – API name for the field
- display_name – Display name for the field
- data_type – Data type for the field
- Object
An example of a complete record would appear as follows:
"custom_fields": [
{
"data_type": "text",
"id": "e92c70fb-1f19-4e7a-ae15-e4d2a24ce543",
"field_id": "a30b59ca-7b29-4e1e-94f0-d496a0e797ab",
"field_name": "location_billing_code",
"field": {
"id": "a30b59ca-7b29-4e1e-94f0-d496a0e797ab",
"name": "location_billing_code",
"display_name": "Location Billing Code",
"data_type": "text"
}
},
"value": "BE-PROD/BOS/179"
}
This example shows reading a populated value of a text string named Location Billing Code that internally is referenced by the API field name of “location_billing_code”.
Writing (POST/PATCH/PUT)
When a custom field exists, creating a value or updating one simply implies passing the custom_fields array as part of the body to a request. For instance, to set the field named “location_billing_code”, one must simply pass a JSON object in the custom_fields array with the field_name and value elements.
The type of the data object should be either string, numeric, or Boolean depending on the custom field type. Date values should ISO standard date strings with timezone information. An example of creating or updating a field follows:
{
“custom_fields”: [
“field_name”: “location_billing_code”,
“value”: “LBS-THX-1138”
]
}
In the above example, this could be a POST to the /buildings endpoint. The example would obviously work as a PATCH given the partial data. A PATCH of custom fields can accompany updates to other fields in the object as well.
Management of Custom Fields
Custom Fields are managed via the /custom_fields endpoints.
Permissions
Permissions in Prism are used to allow users access to specific functionality, such as Work Orders or Preventative Maintenance, as well as specific features such as allowing control of what users can create or close a Work Order.
Permissions are grouped together into Permission Groups which a User may have one or more of. The users’ initial Permission Groups are defined based on the Job Function that a user chooses. The following APIs allow you to see the Job Functions, which are global to the Prism platform, as well as for accessing what Privileges exist and what Permission Groups are defined for the given PMO organization.
GET /job_functions
This will return the Job Function values. These are high-level job functions which we traditionally use to select initial Permission Groups for the user. The results are a standard paged result with the results return returning an array including:
- id – GUID of Job Function
- name – Display name for Job Function
- organization_type – One of pmo, vendor, or tenant for the Organization type related to the Job Function
GET /permissions
This returns the different permissions available in the system. The permissions are assigned to a user in groups (permission groups) and the user has the sum of all permissions across the various groups. Some permissions are implicit and are used but not directly visible for end-user select and are shown with a visible argument that is false. The results are not-paged and include:
- id – GUID of the permission
- name – Internal name of the permission
- display_name – Display name for the permission
- module – May be null or the name of the related BE Module or functionality group; In the case of the module permission, this includes the module id and the module name
- category – May be null or is a sub-category used for visually organizing permissions
- accepted_rights – An array of rights that imply this permission; these are surrogates meaning having these permissions entitles the user to the permission being recorded
- visible – true or false depending on if the permission should be shown
- GET /organizations/management/{{pmo_id}}/permission_groups
Given your PMO Organization ID, this call will return the permission groups available which will, in turn, identify the permissions. This last call will return much of what you need. The results include:
- id – GUID of the permission group
- name – Name of the permission group
- organization_type – Type of organization this permission group relates to; one of pmo, vendor, or tenant
- is_system – Indicates (true or false) if this was user-created or created by BE
- permissions – An array or permissions objects including id, name, module, category, and visible (true or false)
- extended_permissions – The full array of strings of permission names
- system_permissions – The full array of strings of permission names implied for this account including module access (e.g.can_access_module_surveys indicating access to the PoY Surveys module)
Swagger Documentation
The reference documentation, generated from the system, exists in two formats:
FAQs
Is there super data structure for Prism ?
Details: For related entities does Prism support a combined payload structure via API to update all the objects at once. For e.g. Can a Property and User be created and linked via a single API call.
Answer: Prism doesn’t support any sort of super data structure. In the above example, User will have to be created separately and then the property and then the association between User and Property in another API Call.
Are the parent child hierarchies updatable ?
Details: If relationships have been created is it easy to update them. For e.g. There are 2 buildings, building 1 and 2. If a space is created erroneously in building 1 instead of building 2, can the existing space be updated to the new correct building id or does the space need to be deleted and recreated ?
Answer: Most often the relationships API calls support updating the relationships. (need to be verified)
Does Prism support placeholders for certain kinds of data ?
Details: For certain kind of related objects does Prism support any sort of placeholder object or notation.
Answer: Prism doesn’t support any such mechanisms. Any field that is marked as required needs to have a valid value at the time of creation. If it is not required, it can be left empty.
Are there any circular dependencies and what are best practices in handling those relationships?
Answer: Prism generally avoid circular relationships
Whats the best way to pre-seed or batch update data?
Answer: Prism offers a few ways pre-seed the data. Here is a quick summary (See Secondary Options above for details).
- Import CSV Files. The CSV templates can be downloaded from the UI.
- Bulk APIs. Caution: The Bulk API often skip some validations that are usually done when importing CSV files or API requests.
- Regular POST/PATCH API calls
Irrespective the method used, it is recommended to test a small sample set before processing entire data sets.
Whats the best way to keep the data in sync?
Details: Third part systems need to be notified of updates in Prism or need a constant data feed to sync data
Answer: Data sync can be done using two ways
- Webhooks: Only some objects in Prism support webhook notifications. The webhook notification will just contain the ID of the objects and the type of the object and an API request will be necessary to get the full details of the object. The request will always return the most recent version of the object.
- Batch Polling: Use the APIs to fetch data based on date criteria based on updated_at or created fields
It is recommended to always have a batch polling mechanism to catchup even when webhooks are used.
What is the recommended hierarchy to sync data?
Details: Is there a specific order of objects to follow while updating data
Answer: The answer will depend on the object being updated. Generally look for the required fields for a particular API call and that will help determine the order of objects to update. It is generally recommended to update Buildings, Users and Companies first and then other objects.
Is there a sample Postman Collection available to use as a starting point?
Answer: Yes. Please refer to the Prism API.postman_collection.json file attached to this article.
Does Prism have a way to track IDs of entities in external systems?
Answer: Objects in Prism have a field called external_key which can be used for this purpose.
Del vs Deactivate in Prism
Some objects in prism support a deactivation. Refer to our API documentation for which objects support deactivation. Here are some of the most common examples
How can I deactivate a tenant company?
Sample request POST call to /organizations/tenants/{id}/deactivate
{
"building_ids": [
"string"
],
"account_id": "UUID",
"name": "string",
"organization_type": "tenant",
"organization_identifier": "string",
"external_key": "string",
"is_suspended": true
}
Entity | Delete | Deactivate | Comments |
Buildings |
User can access status change OR Actual deactivate as a bulk action through Prism Admin |
Buildings can only be removed or deactivated only our internal support users at this point. | |
Users |
POST /users/:id/deactivate Sample payload { account_id : id new_inspection_assignee : null new_pm_program_assignee : null new_pm_task_assignee : null new_work_order_assignee: null } |
Delete is very powerful – no permission checks It is recommended to use deactivate. |
|
Floors | DELETE /space/:id | Not supported | This will throw an error if there is anything assigned to the Floor (work order, equipment, space, etc). In order to delete a floor, you must manually reassign all work to a new space. |
Suite | DELETE /spaces/:id | Not supported | Deleting a space will re-assign all work orders to the floor the space is on. |
Organizations | POST /organizations/:id/deactivate |
validate - not a PMO, is active, can manage permission, has no active users, check that user has access to all buildings the organization does reassign not closed or completed tasks (anything else not in the below list will need to be explicitly handled):
remove any suites the org is in disable my_coi or jones if enabled marks org as is_active = False |