Introduction

Organizations today are using an increasingly diverse range of online applications to meet their changing needs. As applications become more advanced for specialized functions and tasks, they provide a more efficient and intuitive workflow for organizations to share data.

This diagram shows how applications in a third party system access information from another application via standardized requests called Application Programming Interfaces (APIs), specially defined for the program being called upon. 

In the context of online applications, an API is usually defined as a set of Hypertext Transfer Protocol (HTTP) request messages packaged with definitions for the response messages in Extensible Markup Language (XML) or JavaScript Object Notation (JSON) format.

RESTful APIs

With the number of unique APIs being implemented daily, understanding how each API works can become confusing and time consuming. Representational State Transfer (REST) is a standardized way of creating HTTP APIs. APIs that conform to REST standards and architecture are called RESTful APIs and use a consistent naming scheme for their Universal Resource Locators (URLs), commonly known as the web address seen at the top of your browser.

A resource is a virtual object associated with data. Every resource within an API has its own unique URL. Resources are modeled as a JSON object and are stored in code using the special identifier key:value pair. For example, a resource containing user information stores users' first names and last names using the identifiers, FirstName:value and LastName:value, respectively, in the code. 

The resources for an API are defined using different kinds of parameters. A RESTful API usually uses parameter values in the following ways:

  • With a URL path: …/api/resource/parametervalue
  • With a query path using name value pairs (name=value): …/api?type=user&id=23
Primary API Functions

BIS Safety Software's primary API functions provide a framework for external applications to communicate directly with our servers and complete a variety of functions at any time, including:

  • Creating, updating, or retrieving information from user accounts
  • Retrieving completion statuses, completion dates, and expiry dates for all courses, training records, and forms for each user
  • Retrieving a list of all documents uploaded to a user’s account
  • Retrieving a report on all company locations and roles set up in BIS Safety Software
  • Retrieving a list of classroom calendar events

These API functions can be executed on demand at any time by following the instructions and guidelines outlined in this document. 

The BIS Safety Software API can be accessed through the base URL provided below. 

Base URL
https://www.bissafety.app/rest/v.01
Response Codes

BIS uses 3-digit conventional HTTP response codes to indicate the success or failure of an API request. Generally, the first digit in the 3-digit code designates the following information:

  • 2XX - API request is successful
  • 4XX - the request failed because of what was sent, for example a missing required parameter, a missing or expired token, or an API credential without access to the endpoint.
  • 5XX - the request failed because of an error on the BIS servers. Try again later, and contact BIS Support if it keeps happening.

Errors return a JSON body with error and error_description, for example {"error": "invalid_token", "error_description": "The access token is invalid"}.

Statuserrorerror_descriptionWhat to do
400invalid_requestAuthorization header is missingSend Authorization: Bearer YOUR_BEARER_TOKEN with every call except POST /token and the Open API endpoints.
401invalid_tokenThe access token is invalidThe token is wrong or has expired. Tokens last 3600 seconds (1 hour); request a new one from POST /token.
403access_deniedThe access token does not have access to the requested URIYour API credential is not allowed to call this endpoint. Grant it in Admin > Setup > Integration > API Credentials.
400invalid_requestclient_id, client_secret and grant_type are the required fields.POST /token only. Send all three as form fields.
400unsupported_grant_typeOnly supported grant_type(s) are: client_credentialsPOST /token only. Send grant_type=client_credentials.
401invalid_clientInvalid client_id and/or client secretPOST /token only. Check the credential in Admin > Setup > Integration > API Credentials.
400invalid_requestClient_ID, Client_Secret missing in request headerOpen API endpoints only. Send client_id and client_secret as request headers.
401invalid_credentialsClient_ID, Client_Secret are invalidOpen API endpoints only. Check the credentials your BIS Account Manager gave you.

Paging: endpoints that return lists take offset (how many records to skip) and recordsperpage. The defaults differ per endpoint; see each endpoint's parameters.

Authentication

Applications access BIS Safety Software's APIs by first making a call to our authentication endpoint to acquire a bearer token.

Calls to the authentication endpoint require API credentials. API keys can be generated by users with the Client Security Admin role within your portal. If no one in your organization has this role assigned, please contact your BIS Account Manager to have the Client Security Admin role granted to an appropriate user.

  1. Client ID: A unique secret company identification number 
  2. Client Secret: A secret security key for BIS Safety Software authentication 

The bearer token is used in all following requests to call our APIs. Every call must be preceded by an authorization header containing the bearer token. Your bearer token is also required to set up a custom single sign-on (SSO) for your company, if required.

Your secret API Credentials help protect your company's information and company's user information, so be sure to keep them secure and do not share them in publicly accessible environments.

Endpoint
POST /token
curl -X POST "https://www.bissafety.app/rest/v.01/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "grant_type=client_credentials"
Request parameters
grant_type string Form field required

The only supported value is 'client_credentials'.

client_id string Form field required

The secret unique Client ID given by BIS Account Managers.

client_secret string Form field required

The secret BIS Safety Software Key provided by BIS Account Managers. 

Sample response
{
  "scope": "",
  "access_token": "YOUR_TOKEN",
  "expires_in": 3600,
  "token_type": "bearer"
}
Users

The user object is a critical element of our system. Most third party systems plan to sync users between their system and BIS Safety Software. Using the user API endpoint, you can list, add, update, and deactivate users in BIS Safety Software. Some important parameters used in this User API endpoint, as well as some other API endpoints and the SFTP Import, are discussed below.

Location

API endpoints may have location and location ID code request parameters or include location-based objects. Location refers to the name of the location in the company hierarchy in BIS Safety Software shown in the Users tab. The location ID code refers to the unique location ID code assigned to each location in the company hierarchy, which allows your system to import or move users into correct locations in BIS Safety Software.

Our APIs prioritize the location ID code over the location name, such that users will be added or moved to the location in the hierarchy with the matching location ID code. If the location ID code is not found in BIS Safety Software, the API searches for a matching location name. Either neither the location ID code nor location name can be found, the user will be added to or moved to the set default location. The default location is set in the portal’s company settings.

New locations can be created when APIs are executed using the AddLocation request parameter.

Request Parameters

AddLocation numeric

Allows new locations to be created in the hierarchy shown in the Users tab in BIS Safety Software. By default, the value is “1”, which adds the location. If a parent location ID code is provided and found in BIS Safety Software, the new location is added under the location assigned the parent location ID code. If a parent location ID code is not provided, the new location will be added directly under the highest company location in the hierarchy.

Accepted values: 1 / 0

Company Role

Users can have company roles, which must match the roles set up in BIS Safety Software. You can assign multiple company roles by separating them using a comma. New company roles can be automatically created using the AddRole request parameter. New company roles are added automatically to the company’s training matrix if the training matrix feature is enabled, but no training is assigned to the new role.

Request Parameters

AddRole numeric

Allows new company roles to be created, assigned to users, and added to the training matrix if enabled. The value is “1” by default, which creates and assigns the new role. A message will display “___” if the company role was successfully added and assigned. If the company role does not exist in BIS Safety Software, the user will not be assigned any role.

Accepted values: 1 / 0

Primary Role

Users can have multiple company roles, one of which you can designate as a primary role. Using this User API endpoint, you can add both company roles and primary roles if they do not exist. 

Request Parameters

AddRole numeric

Allows a company role assigned to users to be designated as a primary. The value is “1” by default, which assigns the new primary role. If the value is "0", the API will not process or assign any new primary or company roles. 

Accepted values: 1 / 0

System User Role

Users can be assigned any system user role except the Client Admin role, which controls their permission levels to change your company’s portal and access data within it. When changing existing or assigning new system user roles, they must match user roles in BIS Safety Software. Otherwise, there will be no change to an existing user’s system user role or new users will be given the Learner role by default. (Client admin system user roles cannot be removed using API endpoint calls.)

Subcompany Name

When companies have sub companies, there will be a parent portal and sub portals. Users can be moved between the parent portal and sub portals, as well as between sub portals. The sub company name must match the company name in the sub company’s portal for users to be added to or moved successfully to their location.

Data from sub portals can be included when data is retrieved using API endpoints are executed using request parameters.

Custom Fields

Your company can add custom fields with specified field names and field types to user profile accounts from the Company Setup under the Settings section in the Profile Fields subsection. BIS Safety Software creates a unique ID key for each custom field.

You can find unique custom field keys by accessing the browser’s developer tool (right-click the custom field in the user profile and select Inspect). Under the Elements menu, the html coding for that custom field is highlighted. The unique ID key for the custom field can be identified in the custom field’s special name as the numerical digits following “SpecialFields_”.

In the example, the developer tool shows a custom field for Rehire Date, which shows “name=’SpecialFields_291'”, where the unique ID key is “291”. Objects for custom fields are stored in the code using the identifier key:value pair using the custom field’s unique ID key. In the example, data for Rehire Date is represented as {‘291’:’YYYY-MM-DD’}. Multiple custom fields can be included by separating them with commas; for example, {‘291’:’2021-11-26’,’592’:’1 year term’,’703’:’12345’}.

List Users

Using this API endpoint, you can list up to 1000 users in the sytem. If you have more than 1000 users, then use pagination to list all your users in the system in groups of 1000 or less. The response shows user information, including entries in custom profile fields created in the settings of the portal's Company Setup page. Note: this API endpoint will not list the primary role of users if the Primary user toggle in the Training Matrix module settings in the portal's Setup module is disabled. 

 

Each role's primary field is returned only when the primary role feature is turned on for your company.

Endpoint
GET /user
curl -X GET "https://www.bissafety.app/rest/v.01/user" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software.  To get multiple users, you can pass User ID as comma separated list.

bisinternaluserid numeric Query

System ID of a user in BIS.

location string Query

The location name or location ID code of a specific location in your company hierarchy. The company hierarchy is the company structure shown in the Users tab, which structures your company's employees, contractors, clients, customers, etc. by location, sub locations, departments, or however best meets your company's needs. 

role string Query

The user's specific company role or job title indicated by the role name or code.

status string Query

A filter to get users with certain statuses: active, inactive, or deactivated. By default, the API returns active users "A". If you want to get deactivated users, use the parameter value "I". If you want to get both active and deactivated users, leave the parameter value blank "". 

Please Note: Account Status Active and Inactive are considered as active. The only difference is Inactive account has not yet been activated by user. Deactivated accounts are the once that we deactivated by admins and will not longer allowed to access the system.

Accepted values: A / I / ""

firstname string Query

Filters users by first name.

lastname string Query

Filters users by last name.

birthdate date Query

Filters users by their birthdate specified in the date format (YYYY-MM-DD).

modified date Query

Filter users that were added or modified after a certain date time specified in ISO date format (YYYY-MM-DDTHH:MM:SSZ).

includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies by specifying "1". By default, sub companies are not included "0".

Accepted values: 0 / 1

offset numeric Query

Offset the results by a certain value. By default, the offset is zero "0". 

recordsperpage numeric Query

Limit the number of users that are returned up to a maximum of 1000. 

includeqrcode numeric Query

When value is 1, user QR code data is included in response.

Sample response
{
  "recordsperpage": "1",
  "offset": "0",
  "count": 770,
  "users": [
    {
      "companyrole": "Sample Role 1|Sample Role 2",
      "companyroles": [{
        "code": "00001",
        "name": "Sample Role 1",
        "primary": "true"
      },{
        "code": "00002",
        "name": "Sample Role 2",
        "primary": "false"
      }],
      "location": "eCommerce Users",
      "cellphone": "16472702345",
      "startdate": "",
      "evaluator": "",
      "firstname": "Aarian",
      "stateprov": "Alberta",
      "BISInternalUserID": 2145533,
      "birthdate": "1985-05-01",
      "homephone": "17803862134",
      "locationcode": "",
      "subcompanyname": "In-House BIS",
      "status": "A",
      "middlename": "A",
      "country": "Canada",
      "lastname": "Hosein",
      "userid": "B0001053",
      "username": "AHosein3",
      "ProfilePicApproved": 0,
      "workphone": "17803862134",
      "postalcode": "T0B 2V0",
      "language": "English",
      "emergencyContact": "Jane",
      "emergencyContactPhone": "",
      "email2": "test1@test.com",
      "email1": "test2@test.com",
      "ProfilePic": "",
      "employer": "",
      "city": "Edmonton",
      "address": "9999 51st Street",
      "sin": "678355412",
      "terminationdate": "",
      "qrcode": "C7A16E39AA2F03FBB4B47792457EB99F91643B26D6346D395DFEAE81E1C69C1846343D27855A1377",
      "modified": "ISO Date/Time 2023-01-01T10:10:00Z",
      "CUSTOM FIELD NAME 1": "VALUE",
      "CUSTOM FIELD NAME 2": "VALUE",
      "membership": {
        "id": "ID",
        "name": "Elite",
        "expiryDate": "YYYY-MM-DD",
        "dateAdded": "ISO Date/Time 2023-01-01T10:10:00Z"
      }
    }
  ]
}
Import Users

You can add, update, and deactivate users using this API endpoint.

Returns an array of result objects in the same order as the input users array. Each result includes an error flag (0 = successfully added/updated, 1 = failed) along with status/logs.

Users are matched in this order: bisinternaluserid, then hrsystemid, then email1 (only when useEmailAsIdentifier is 1), then userid. Only the first identifier present in the record is used. If no account matches on hrsystemid or email1, the API falls back to userid before creating a new account.

When an account is created with an hrsystemid, that ID is stored against the account. Sending the same hrsystemid later updates that same account and writes the userid (Employee ID) onto it once it is supplied, so accounts can be created before an Employee ID exists.

An hrsystemid is added to an account, never replaced. If you send a corrected or reassigned hrsystemid for a user, the earlier value stays on that account and can still match later imports. Send a value you do not plan to change.

Endpoint
POST /user
curl -X POST "https://www.bissafety.app/rest/v.01/user" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "users=[{'userid': '123456','firstname': 'Test','lastname': 'User'}]"
Request parameters
users json Form field required

This parameter is an array of user objects in JSON format. A maximum of 200 users can be imported into BIS Safety Software at a time.

Sample data
[
  {
    "userid": "String - Required unless hrsystemid, bisinternaluserid, or email1 (when useEmailAsIdentifier is 1) is provided - Unique identifier from your (third-party) system. Maps to the **Employee ID** field in BIS and is used to match existing accounts on import. This is NOT the internal BIS user ID (see bisinternaluserid).",
    "hrsystemid": "String - Optional - Persistent unique ID of the user in your HR system (for example BambooHR, SuccessFactors, ADP). Stored against the account and used to match the user on later updates when userid, name or email have changed. Recommended when accounts are created before an Employee ID exists.",
    "firstname": "String - Required",
    "preferredname": "String - Optional",
    "middlename": "String - Optional",
    "lastname": "String - Required",
    "location": "String - OPTIONAL - If location or locationcode is not provided then new users will be added under default location",
    "locationcode": "String - OPTIONAL",
    "parentlocation": "String - OPTIONAL",
    "parentlocationcode": "String - OPTIONAL",
    "companyrole": "String - OPTIONAL",
    "primaryrole": "String - OPTIONAL - Specifies the user's primary role. The value must exist within the role list (companyrole). If the specified role is not part of companyrole, it will be automatically removed or ignored during processing",
    "email1": "String - Recommended",
    "email2": "String - Optional",
    "address": "String - Optional",
    "city": "String - Optional",
    "country": "String - Optional - Default Portal's country",
    "stateprov": "String - Optional - Default Portal's state/province",
    "postalcode": "String - Optional",
    "workphone": "String - Optional",
    "cellphone": "String - Optional",
    "homephone": "String - Optional",
    "evaluator": "String - Optional - User's manager userid",
    "evaluator2": "String - Optional - User's Evaluator 2 field userid",
    "birthdate": "Date - Optional - Date YYYY-MM-DD format",
    "startdate": "Date - Optional - Date YYYY-MM-DD format",
    "terminationdate": "Date - Optional - Date YYYY-MM-DD format",
    "employer": "String - Optional",
    "status": "String Required - Accepted value A and I",
    "language": "String - Optional - Accepted value English/French/German/Español - Default English",
    "emergencyContactName": "String - Optional - Emergency contact name",
    "emergencyContactMobile": "String - Optional - Emergency contact phone",
    "customfields": "Struct - Optional - this is structure of all custom fields with values - Default {}",
    "addlocation": "Numeric - Optional - What should be done if location provide does not exists - Accepted value 0/1 - Default 1",
    "updatelocation": "Numeric - Optional - update location - Accepted value 0/1 - Default 0",
    "addParentLocation": "Numeric - Optional - add parent location if does not eixsts - Accepted value 0/1 - Default 0",
    "useDefaultLocation": "Numeric - Optional - What should be done if location provide does not exists and addlocation is 0 - Accepted value 0/1 - Default 1",
    "addrole": "Numeric - Optional - What should be done if company role provide does not exists - Accepted value 0/1 - Default 1",
    "proceedOnInvalidRole": "Numeric - Optional - Used only when addrole is 0. Pass 1 to still save the user when a company role passed does not exist. The missing roles are skipped, the valid roles are assigned, and the status returns 'There are invalid company roles.' With 0 the user is not saved and the status returns 'Company role does not exists.' - Accepted value 0/1 - Default 0.",
    "addsystemroles": "String - Optional - list of system roles that need to be added to user",
    "removesystemroles": "String - Optional - list of system roles that need to be removed from user",
    "subcompanyname": "Optional - Only needed when a company has sub companies and want to update users under sub company",
    "socialinsurancenumber": "String - Optional",
    "bisinternaluserid": "Optional - Unique ID in BIS",
    "onlyUpdateAPICompanyRole": "Optional - If 1 then do not remove roles added by admins, only remove roles added by API - Accepted value 0/1 - Default 0",
    "profilePicture": "Optional - You can pass Base64 String to update the profile picture for the user. File size is limited to 2MB.",
    "skipMoveUser": "Numeric - Optional - Pass 1 if you do not want users to be moved from existing location to passed/default location - Accepted value 0/1 - Default 0.",
    "skipaccountswithuserid": "Numeric - Optional - Pass 1 if you do not want the users with userid setuo in there account be udpated by other user account details - Accepted value 0/1 - Default 0.",
    "sendInvitationEmailOnCreation": "Numeric - Optional - Pass 1 if you want the users to receive account invitation email upon account creation - Accepted value 0/1 - Default 0.",
    "useEmailAsIdentifier": "Numeric - Optional - Pass 1 to find the user to update by email1 when bisinternaluserid and hrsystemid are not passed. userid is then not required as long as email1 is passed. If no account matches email1, the API tries userid next. If more than one account has that email1, the user is not saved - Accepted value 0/1 - Default 0.",
    "useNameAsIdentifier": "Numeric - Optional - Pass 1 if you want to allow API to find users to update using only the firstname and lastname, when the primary identifiers are not passed - Accepted value 0/1 - Default 0."
  }
]
returnlogs numeric Form field

Returns additional logs of each user field updated.

Accepted values: 1 / 0

Sample response
[
  {
    "userid": "123456",
    "status": "Updated.",
    "logs": ["Lastname updated to Smith."],
    "error": 0
  },
  {
    "userid": "4554455",
    "status": "Potential duplicates found.",
    "logs": [],
    "error": 1
  },
  {
    "userid": "775588",
    "status": "Added.",
    "logs": [],
    "error": 0
  }
]
Get Documents

You can use this API endpoint to get the documents that are uploaded in a user's profile in BIS Safety Software.

Endpoint
GET /user/documents
curl -X GET "https://www.bissafety.app/rest/v.01/user/documents?userid=USER_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query required

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software. 

Sample response
{
  "documents": [{
    "documenturl": "http://www.bissafety.app/assets/UserDriverDocument/MHR.12.07.17 R1.xlsx",
    "documentname": "Sachin Test"
  }, {
    "documenturl": "http://www.bissafety.app/assets/UserDriverDocument/2018-02-14_ABC.png",
    "documentname": "2018-02-14_0913.png"
  }]
}
Login
Request parameters
username string Form field required

Username used by user to login to BIS.

password string Form field required

Password used by user to login to BIS.

Sample response
{
  "status": "success",
  "user": {
    "lastname": "LASTNAME",
    "firstname": "FIRSTNAME",
    "bisinternaluserid": "BIS_INTERNAL_USERID",
    "email": "EMAIL"
  }
}
Site Activity

You can use this API endpoint to get last date and time the user accessed this site.

The response from this API will be the exact same records parameter, but with two additional fields status and message.

Endpoint
POST /user/siteactivity
curl -X POST "https://www.bissafety.app/rest/v.01/user/siteactivity" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode 'records=[{"userid": "BIS0956e16", "siteid": "1232Test", "activityDate": "2023-08-07 04:30:00.000+05:30"}, {"userid": "BIS0956e16", "siteid": "REDTW 23123", "activityDate": "2023-09-11 19:19:00.000+05:30"}]'
Request parameters
records json Form field required

This parameter is an array of training record objects in JSON format. A maximum of 200 records can be imported into BIS Safety Software at a time.

Sample data
[
    {
        "userid": "String - Required - Unique userid in third party system",
	"siteid": "String - Required - Unique siteid in third party sysytem",
	"activityDate": "Date in ISO format - Required - The last date and time the user accessed the site."
    }
]
Sample response
{
    "records": [
        {
            "message": "",
            "status": "success",
            "activityDate": "2023-08-07 04:30:00.000+05:30",
            "userid": "BIS0956e16",
            "siteid": "1232Test"
        },
        {
            "message": "",
            "status": "success",
            "activityDate": "2023-09-11 19:19:00.000+05:30",
            "userid": "BIS0956e16",
            "siteid": "REDTW 23123"
        }
    ]
}
Training

You can get training records for users using two API endpoints described below. 

Completed Training

You can get users' completed training. The results will include all online courses, forms, and historical completed training records.

Note: If userid or bisinternaluserid or coursecode or combination of email and lastname are not passed in and from/to dates are not available, the API gets the records that were completed in the past 24 hours for all users in the portal. 

Endpoint
GET /training
curl -X GET "https://www.bissafety.app/rest/v.01/training?userid=USER_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software. 

bisinternaluserid numeric Query

System ID of a user in BIS.

coursecode string Query

External course id of the course to get completions for a specific course.

email string Query

The email address in the profile account of each user in your system. Both the email and lastname request parameters must be passed to this API endpoint to have a successful API response.

lastname string Query

The last name in the profile account of each user in your system. Both the lastname and email request parameters must be passed to this API endpoint to have a successful API response.

fromdate date Query

All training completed on or after the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are blank, then the training completed in the previous day from the time this API endpoint is called will be returned.

NOTE: Total number of days between the fromdate and todate must be 30 days or less.

todate date Query

All training completed on or before the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are blank, then the training completed in the previous day from the time this API endpoint is called will be returned.

NOTE: Total number of days between the fromdate and todate must be 30 days or less.

onlypassed numeric Query

Returns the completed training that is passed and accepted by Admins by default. If the value is specified as "0", all completed training is returned, including passed, failed, and training not yet accepted.

Accepted values: 1 / 0

status string Query

Leave blank to retrieve results for all course types.

Accepted values: Public / Private

type string Query

The completed training type: training record (TR), form (AF), or Online Course (OC). If this parameter value is left blank, records for all training types will be provided. 

Accepted values: TR / AF / OC

deletedrecord numeric Query

This parameter is used to get deleted Training Records only. By default, this parameter is set to 0

Accepted values: 0 / 1

includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies by specifying "1". By default, sub companies are not included "0".

Accepted values: 0 / 1

includeincompletecourses numeric Query

This parameter is used to get incomplete course completions. By default this parameter is set to 0.

Accepted values: 0 / 1

datefilter string Query

completion (default): fromdate/todate filter on the completion date - the historical behavior.

modified: incremental sync mode, pulls "what changed since my last sync". fromdate/todate filter on the record's last-modified watermark and are treated as UTC dates covering full UTC days (a time component, if supplied, is ignored; the window closes at 23:59:59 UTC of todate; no dates returns the last 24 hours of changes). The response field modifiedon carries the exact last-changed timestamp (ISO 8601, UTC) the watermark filter uses; it is null only for rows that were never modified, such as incomplete rows returned via includeincompletecourses=1. modifieddate keeps its historical behavior (Mountain Time date, blank when never modified). Records match on completionid + completiontype for upsert. Other response dates remain Mountain Time, day granularity. Same 30-day window cap and same filters as the default mode.

Sample data
modified
Sample response
{
  "training": [{
    "results": [{
      "completionid": 1342409,
      "permissionid": 1323433,
      "completionstatus" : "completed",
      "completiontype": "online",
      "certificate": "https://www.bissafety.app/index.cfm?action=trm.downloadcertificate&data=65E25EDSD6EE0148462E",
      "certificatefiletype": "pdf",
      "courseid": "",
      "internalcourseid": "",
      "coursename": "100-07 Propane Hose Inspection and Testing",
      "modifieddate": "",
      "modifiedon": "",
      "issuingauthority": "",
      "expirydate": "",
      "completiondate": "2024-01-18",
      "pass": true,
      "score": 80,
      "trainerprovstate": "Ontario",
      "courseinstructor": "",
      "internal": 0,
      "addeddate": "2018-01-24",
      "trainer": "CPA - Propane Training Institute",
      "deleted": 0
    }, {
      "completionid": 1272386,
      "permissionid": 1323433,
      "completionstatus" : "completed",
      "completiontype": "online",
      "certificate": "https://www.bissafety.app/index.cfm?action=trm.downloadcertificate&data=65E25EDSD6EE0148462E",
      "certificatefiletype": "png",
      "courseid": "",
      "internalcourseid": "",
      "coursename": "Atmospheric Gas Tester.",
      "modifieddate": "",
      "modifiedon": "",
      "issuingauthority": "HSE Integrated",
      "expirydate": "2025-10-17",
      "completiondate": "2021-10-17",
      "pass": true,
      "score": 80,
      "trainerprovstate": "Alberta",
      "courseinstructor": "",
      "internal": 0,
      "addeddate": "2017-10-26",
      "trainer": "HSE Integrated Training",
      "deleted": 0
    }],
    "lastname": "User",
    "userid": "32",
    "username": "tuser",
    "firstname": "Test",
    "email": "test2@test.com",
    "subcompanyname": "In-House BIS"
  }, {
    "results": [{
      "completionid": 1983540,
      "permissionid": "",
      "completionstatus" : "completed",
      "completiontype": "training",
      "certificate": "https://www.bissafety.app/index.cfm?action=trm.downloadcertificate&data=65E25EDSD6EE0148462E",
      "certificatefiletype": "pdf",
      "courseid": "",
      "internalcourseid": "",
      "coursename": "Carte de conducteur d'embarcation de plaisance",
      "modifieddate": "",
      "modifiedon": "",
      "issuingauthority": "Formation Nautique Québec",
      "expirydate": "",
      "completiondate": "2022-01-19",
      "pass": true,
      "score": 80,
      "trainerprovstate": "Quebec",
      "courseinstructor": "",
      "internal": 0,
      "addeddate": "2019-01-22",
      "trainer": "Formation Nautique Québec",
      "deleted": 0
    }],
    "lastname": "User",
    "userid": "1111",
    "username": "test",
    "firstname": "Test",
    "email": "test@test.com",
    "subcompanyname": "In-House BIS"
  }]
}
Online Course Result

This API endpoint returns all completed, in progress, and not started online courses with their results and progress details.

Endpoint
GET /training/online
curl -X GET "https://www.bissafety.app/rest/v.01/training/online?userid=USER_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query required

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software. 

bisinternaluserid numeric Query

System ID of a user in BIS. Note: If this parameter is passed then userid parameter is not required.

courseid string Query

The course ID set up for the online course and specific to each company. 

includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies by specifying "1". By default, sub companies are not included "0".

Accepted values: 0 / 1

Sample response
{
  "training": [{
    "results": [{
      "datestarted": "2021-10-06 12:35:52",
      "Status": "In Progress Section 2/2",
      "score": "",
      "pass": "",
      "isrepeated": 0,
      "ID": 4654238,
      "datefinished": ""
    }],
    "dateadded": "2021-10-05 23:00:00",
    "type": "Regular course/exam",
    "Name": "royce test default completon fee 1"
  }, {
    "results": [{
      "datestarted": "2021-10-08 06:50:28",
      "Status": "Completed with 100%",
      "score": 100.0,
      "pass": "Yes",
      "certificate": "",
      "certificatefiletype": "",
      "isrepeated": 0,
      "ID": 4660071,
      "datefinished": "2021-10-08 07:36:54"
    }],
    "dateadded": "2021-10-07 23:00:00",
    "type": "SCORM course",
    "Name": "Office Safety - Marcom Test Course for OCWA"
  }, {
    "results": [{
      "datestarted": "",
      "Status": "Not Started",
      "score": "",
      "pass": "",
      "isrepeated": "",
      "ID": "",
      "datefinished": ""
    }],
    "dateadded": "2020-12-23 00:00:00",
    "type": "Regular course/exam",
    "Name": "04 WHMIS Worker Site Specific Update Training Information v2"
  }]
}
Push Training Records

This API endpoint imports training record.

The response from this API will be the exact same records parameter, but with two additional fields status and message

Endpoint
POST /training
curl -X POST "https://www.bissafety.app/rest/v.01/training" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "records=[{'userid': '123456','courseid': 'COURSEID','completiondate': '2021-09-25','score': '100','expiryDate': '2030-12-31'}]"
Request parameters
records json Form field required

This parameter is an array of training record objects in JSON format. A maximum of 200 records can be imported into BIS Safety Software at a time.

 

When archiveOldRecords is passed as 1, API will find records for the same course and user that were completed prior to the record being added and archive those records. If record being added has completion date prior to the one already exists in the system then API will not add the record.

Sample data
[
  {
    "userid": "String - Required - Unique userid in third party system",
    "courseid": "String - Required - Unique customer course id",
    "completiondate": "Date - Required - Date YYYY-MM-DD format",
    "score": "Number - Optional - Accepted value 0 to 100 - Default 100",
    "trainingprovider": "String - OPTIONAL - Training provider for the course",
    "expirydate": "Date - Optional - Date YYYY-MM-DD format - Only applicable if 'Expiry Override' is enabled for the course",
    "archiveOldRecords" : "Number - Optional - Accepted value 1 - Default ''"
  }
]
includesubcompany numeric Form field

This parameter is used for the companies that have sub companies. You can include users for all sub companies. By default, sub companies are not included "0".

Accepted values: 0 / 1

Sample response
{
  "records": [{
    "message": "",
    "status": "success",
    "score": "86",
    "courseid": "TTTTEEDDDTT",
    "userid": "123456",
    "completiondate": "2021-11-08"
  }, {
    "message": "Duplicate completion record",
    "status": "error",
    "score": "86",
    "trainingprovider": "Test",
    "courseid": "COURSEID",
    "userid": "121212",
    "completiondate": "2021-11-08"
  }]
}
Courses in Course Pool

This API endpoint gets a list of all courses in your course pool.

Endpoint
GET /training/contentpoolcourses
curl -X GET "https://www.bissafety.app/rest/v.01/training/contentpoolcourses" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
modified date Query

All online courses that were modified after the date(yyyy-mm-dd format) will be returned.

Sample response
{
  "courses": [
    {
      "ceu": 0.3,
      "image": "",
      "description": "Description rich text content",
      "video": "",
      "courseid": "COURSE_ID_2",
      "internalcourseid": "INTERNAL_COURSE_ID",
      "contentowner": "BIS Safety Software",
      "type": "Internal",
      "priceDetails": {
        "membership": [
          {
            "price": 142.5,
            "id": "ID",
            "name": "Elite"
          }
        ],
        "default": 150.00
      },
      "name": "Sample Course Name 2"
    }
  ]
}
Create Course Code

This API endpoint creates a course code for the passed course ID and responds with the course code.

Endpoint
POST /training/createcoursecode
curl -X POST "https://www.bissafety.app/rest/v.01/training/createcoursecode" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "courseid=COURSEID" \
-d "quantity=QUANTITY" \
-d "location=LOCATION" \
-d "expirydate=EXPIRYDATE" \
-d "notes=NOTES" \
-d "upgrade=UPGRADE"
Request parameters
courseid string Form field required

The Course ID you get from /contentpoolcourses needs to be passed here.

quantity numeric Form field required

Number of seats to be added to the course code.

location string Form field required

The location name where users will be added to when they register using the course code.

expirydate date Form field required

Expiry date for the course code in YYYY-MM-DD date format.

notes string Form field required

Notes about the code created.

upgrade numeric Form field

Add Virtual Proctoring to the course code. By default, the upgrade is zero "0". 

Accepted values: 0 / 1

Sample response
{
  "status": "success",
  "coursecode": "COURSECODE"
}
Training Courses

This API endpoint gets all the training courses available in the training record management module, including classroom courses. Training courses may or may not be linked directly to online courses. 

The priceDetails, courselink, policy, requirements and duration fields are returned only when you filter with coursetype=classroom.

Endpoint
GET /training/courses
curl -X GET "https://www.bissafety.app/rest/v.01/training/courses" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies. By default, sub companies are not included "0".

Accepted values: 0 / 1

coursetype string Query

Filters training courses. all (default) returns the full catalog with base fields. classroom returns only classroom calendar courses and adds priceDetails, courselink, policy, and requirements.

modified date Query

All courses that was modified after the date(yyyy-mm-dd format) will be returned.

Sample response
{
  "courses": [{
    "trainingprovider": "TEST PROVIDER",
    "courseid": "",
    "expiry": 0,
    "specificexpiryyear": "",
    "specificexpirymonth": "",
    "contentowner": "TEST OWNER",
    "specificexpirydate": "",
    "name": "TEST NAME",
    "subcompanyname": "In-House BIS",
    "status": "Inactive",
    "internalcourseid": 10002961,
    "floatingexpiryyear": "",
    "expirytype": "",
    "hourspercourse": "2",
    "priceDetails": {
      "default": 150.00,
      "membership": [
        {
          "id": "1234567890",
          "name": "Member Tier",
          "price": 120.00
        }
      ]
    },
    "courselink": "https://www.example.com/v1/index.cfm?action=classroom.coursedetails&company={companyid}&course={courseid}",
    "policy": "Cancellation policy text.",
    "requirements": {
      "participant": "Participant requirement details.",
      "instructor": ""
    },
    "duration": {
      "days": 1,
      "schedule": [
        {
          "end": "12:00 PM",
          "start": "08:30 AM"
        }
      ]
    }
  }]
}
Forms

There are two API endpoints that can be used to get form data and completed forms. 

Get Form Data

This API endpoint returns data entered by users into specific fields for a particular form. The data also includes form completion records. 

Endpoint
GET /form/response
curl -X GET "https://www.bissafety.app/rest/v.01/form/response?formid=FORM_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
formid string Query required

Data is fetched from the form with this form ID.

fields string Query

The list of fields (by field ID) in each form to include in the data returned. Field IDs are assigned in the Forms Builder, and multiple field IDs are separated by commas (e.g. TF_10,DD_11,CH_12, etc.). 

filter string Query

A JSON object structure (field and and value combination) to filter results for certain user entries (e.g. {"DD_11":"VALUE1", "CH_12":"VALUE2"}).

includeinprogress numeric Query

By default, data is only returned for completed forms "0". If specified as "1", data for in progress forms is also included with data from completed forms.  

Accepted values: 0 / 1

fromdate date Query

All data in the form entered by users on or after the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are blank, then the form data entered in the previous day from the time this API endpoint is called will be returned.

todate date Query

All data in the form entered by users on or before the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are blank, then the form data entered in the previous day from the time this API endpoint is called will be returned.

offset numeric Query

Offset the results by a certain value. By default, the offset is zero "0". 

recordsPerPage numeric Query

Limit the form data returned by the number of different users entering data up to a maximum of 1000.

modified date Query

Filters form completions that were completed or updated after a certain date time in ISO date format (YYYY-MM-DDTHH:MM:SSZ).

completionid string Query

Use this parameter to select data for a specific completion (you can only provide one ID per request). The ID must be in the format "H_{id}" or "E_{id}" format. 

Sample data
H_99999999 / E_99999999
Sample response
{
  "recordsperpage": 100,
  "OFFSET": 1,
  "COUNT": 2,
  "formName": "Form Title",
  "formdata": [
    {
      "FIELDS": [{
        "fieldtype": "textfield",
        "label": "Test FIELD 1",
        "id": "TF_93",
        "VALUE": "aaaaaaaaaa"
      }, {
        "fieldtype": "textfield",
        "label": "TEXT FIELD 2",
        "id": "TF_95",
        "VALUE": 0
      }],
      "STATUS": "Inprogress - Stage 1",
      "startdate": "2021-06-09",
      "lastname": "Asif",
      "userid": "testuser",
      "firstname": "Test",
      "email": "test@test.com",
      "completiondate": "",
      "completionid": "E_123456",
      "completiontype": "Asset",
      "eventID": 111222,
      "customformid": "TT-10001",
      "lastupdateddate": "2021-06-10T10:10:00Z"
    }, 
    {
      "FIELDS": [{
        "fieldtype": "attendance",
        "label": "Attendance FIELD",
        "id": "AL_7",
        "VALUE":  [{
          "NAME": "NAME (username)",
          "dateadded": "ISO DATE/TIME 2023-01-01T10:10:00Z",
          "signature": "URL https://www.bissafety.app/signature.png"
        },{
          "NAME": "NAME (username)",
          "dateadded": "ISO DATE/TIME 2023-01-01T10:10:00Z",
          "signature": ""
        },{
          "NAME": "NAME (username)",
          "dateadded": "ISO DATE/TIME 2023-01-01T10:10:00Z",
          "signature": ""
        }]
      }, {
        "fieldtype": "textfield",
        "label": "TEXT FIELD 2",
        "id": "TF_95",
        "VALUE": "TEXT FIELD VALUE"
      }, {
        "fieldtype": "taskassignment",
        "label": "Corrective Actions",
        "id": "TK_2",
        "VALUE": [{
          "taskid": 145247,
          "taskname": "Hazards Test",
          "status": "completed"
        }]
      }],
      "STATUS": "completed",
      "startdate": "2021-06-15",
      "lastname": "Asif",
      "userid": "testuser",
      "firstname": "Test2",
      "email": "test2@test.com",
      "completiondate": "2021-06-15",
      "completionid": "H_985476",
      "completiontype": "User",
      "eventID": null,
      "customformid": "TT-10002",
      "lastupdateddate": "2021-06-15T10:10:00Z"
    }
  ]
}
Get Completions

This API endpoint gets completion records for forms.

Endpoint
GET /form/completions
curl -X GET "https://www.bissafety.app/rest/v.01/form/completions?formid=FORM_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
formid string Query

The completion records are fetched for the form with this form ID. 

NOTE: Required if fromdate and todate parameters are not provided.

filter string Query

A JSON object structure (field and and value combination) to filter results for certain user entries (e.g. {"DD_11":"VALUE1", "CH_12":"VALUE2"}).

fromdate date Query

All completion records on or after the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are blank, then the completion records in the previous day from the time this API endpoint is called will be returned. The total number of days between the fromdate and todate must be less than 180 days.

NOTE: Required if the Form ID is not provided. 

todate date Query

All completion records on or before the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are blank, then the completion records in the previous day from the time this API endpoint is called will be returned. The total number of days between the fromdate and todate must be less than 180 days.

NOTE: Required if the Form ID is not provided. 

offset numeric Query

Offset the results by a certain value. By default, the offset is zero "0". 

recordsPerPage numeric Query

Limit the number of form completion records up to a maximum of 1000. 

includeformpdf numeric Query

If this is set to 1, then a temporary link(valid for 30 minutes) to the form PDF will be included in the API response.

Accepted values: 0 / 1

completionid string Query

Use this parameter to select data for a specific completion (you can only provide one ID per request). The ID must be in the format "H_{id}" or "E_{id}" format. 

Sample data
H_99999999 / E_99999999
eventhistoryid numeric Query

Pass the value of the Event ID you want to fetch form completions for.

modifieddate date Query

Returns only completion records whose modified timestamp falls within this UTC calendar day, in the date format (YYYY-MM-DD). This is an exact-day match, not a "changed since" cursor — a record modified on any other UTC day is excluded.

Matching records include a modifieddate response key containing the modified timestamp of the record as an ISO 8601 datetime in UTC (empty string when no modified timestamp is stored).

This parameter can be supplied on its own — when it is present, the requirement to supply either formid or (fromdate and todate) is waived.

Sample data
2026-07-23
assetid string Query

Returns only completions linked to this asset. Use the asset ID returned by the GET /asset endpoint.

For asset completions this matches the asset the form was completed on. For user completions it matches any asset selected in an asset field of that completion.

If both assetid and serialnumber are supplied, assetid is used and serialnumber is ignored.

An asset ID that cannot be read returns HTTP 400 (invalid_request / "Invalid asset ID"); an asset ID that does not belong to your company returns HTTP 404 (not_found / "Asset not found").

This parameter can be supplied on its own — when it is present, the requirement to supply formid, modifieddate or (fromdate and todate) is waived.

serialnumber string Query

Alternative to assetid. Returns only completions linked to the active company asset with this exact serial number, and filters the same way assetid does.

Ignored when assetid is also supplied.

If no active asset matches, HTTP 404 is returned (not_found / "Asset not found"). If more than one active asset shares the serial number, HTTP 404 is returned with "Multiple assets found for serial number: {value}" — use assetid in that case.

This parameter can be supplied on its own — when it resolves to an asset, the requirement to supply formid, modifieddate or (fromdate and todate) is waived.

Sample data
SN-100234
bisinternaluserid numeric Query

Returns only completions belonging to this user. Use the value of the BISInternalUserId key returned in completion records.

Unknown IDs are not rejected — they simply return no completions.

This parameter cannot be used on its own: one of formid, modifieddate, an asset filter or (fromdate and todate) is still required.

Sample data
123456
Sample response
{
  "recordsperpage": 500,
  "offset": 0,
  "count": 2,
  "completions": [{
    "startdate": "2020-10-28",
    "form": "Incident Report Form",
    "BISInternalUserId": 123456,
    "firstname": "Firstname",
    "email": "",
    "formid": 8980,
    "customformid": "TT-10001",
    "completiondate": "2020-10-28",
    "modifiedon": "2020-10-29T14:23:45Z",
    "userlocation": "Location 4",
    "assetname": "3 - Nick Testing ",
    "lastname": "Lastname",
    "userid": "0000000",
    "completiontype": "Asset",
    "completionid": "E_123456",
    "assetlocation": "",
    "stages": [
      {
        "order": 1,
        "stage": "Stage 1",
        "submitted": "2021-02-25T10:10:00Z"
      },
      {
        "order": 2,
        "stage": "Stage 2",
        "submitted": "2021-02-25T10:10:00Z"
      }
    ],
    "pdf": "{link_to_pdf}"
  }, {
    "startdate": "2021-05-06",
    "form": "Incident Report Form",
    "BISInternalUserId": 123456,
    "firstname": "Firstname",
    "email": "",
    "formid": 8980,
    "customformid": "TT-10002",
    "completiondate": "2021-05-06",
    "modifiedon": "2021-05-07T09:41:12Z",
    "userlocation": "Location 4",
    "assetname": "TestSr",
    "lastname": "Lastname",
    "userid": "0000000",
    "completiontype": "User",
    "completionid": "H_123456",
    "assetlocation": "Location 2",
    "stages": [
      {
        "order": 1,
        "stage": "Stage 1",
        "submitted": "2023-12-05T10:10:00Z"
      }
    ],
    "pdf": "{link_to_pdf}"
  }]
}
Get Form Fields

This API endpoints returns form fields for a given form ID.

Endpoint
GET /form
curl -X GET "https://www.bissafety.app/rest/v.01/form?formid=FORM_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
formid string Query required

The completion records are fetched for the form with this form ID.

Sample response
{
    "formname": "Encryption form",
    "success":1,
    "formfields": {
        "encryptionKeyEnabled": true,
        "form": {
            "fields": [
                {
                    "learner": 0,
                    "max": 0,
                    "dbid": 972723,
                    "layout": 1,
                    "evaluator": 0,
                    "pdffieldid": 0,
                    "selectedMoveToLocationName": "",
                    "errprMsg": "",
                    "description": "Form/assessment description",
                    "userMoveOption": 0,
                    "id": "FT_1",
                    "type": "formtitle",
                    "subtype": "",
                    "userReactivationOption": 0,
                    "restrictSpace": 0,
                    "size": 12,
                    "required": 0,
                    "selectedMoveToLocation": 0,
                    "trackid": "264b09ca-6b9d-450e-b3a4-edb33c7e2aa4",
                    "hidden": 0,
                    "hideTitle": 0,
                    "descriptionasTT": 0,
                    "lockUserManagementOptions": 0,
                    "haserror": 0,
                    "hideSigningInstructions": 0,
                    "min": 0,
                    "userMoveToLocation": "",
                    "actionrulekeys": [],
                    "userDeactivationOption": 0,
                    "catpoints": {},
                    "title": "Encryption form",
                    "rules": {},
                    "inherited": 0,
                    "readonly": 0
                },
                {
                    "lengthunit": "characters",
                    "learner": true,
                    "max": 10,
                    "texttype": "all",
                    "dbid": 972726,
                    "fieldInFT": false,
                    "layout": 1,
                    "evaluator": true,
                    "pdffieldid": 0,
                    "selectedMoveToLocationName": "",
                    "errprMsg": "",
                    "description": "Text field",
                    "userMoveOption": 0,
                    "id": "TF_4",
                    "lengthlimitenabled": false,
                    "type": "textfield",
                    "subtype": "email",
                    "userReactivationOption": 0,
                    "restrictSpace": 0,
                    "size": 12,
                    "required": false,
                    "selectedMoveToLocation": 0,
                    "trackid": "b6daaf2e-a803-437f-8857-3b9de3b7a36f",
                    "hidden": false,
                    "hideTitle": false,
                    "descriptionasTT": false,
                    "lockUserManagementOptions": 0,
                    "haserror": 0,
                    "hideSigningInstructions": 0,
                    "min": 3,
                    "userMoveToLocation": "",
                    "actionrulekeys": [],
                    "userDeactivationOption": 0,
                    "catpoints": {},
                    "title": "Title",
                    "rules": {},
                    "inherited": 0,
                    "readonly": false
                }
            ]
        },
        "taskLinkedFields": [],
        "required": [],
        "actionrule": {},
        "labelInFormTitle": false,
        "sinFields": [],
        "sequence": 6,
        "actionrulekeys": [],
        "validate": [
            "TF_4"
        ],
        "companyId": 1,
        "menu": {
            "keys": []
        },
        "points": {},
        "angular": true
    }
}
Get Form PDF Link

This endpoint creates a secure, time-limited download link for PDF report of completed form submissions. The PDF can be generated using either the default layout or a specific custom layout.

Endpoint
GET /form/completion-pdf
curl -X GET "https://www.bissafety.app/rest/v.01/form/completion-pdf?completionid=E_00000000" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
completionid string Query required

Completion identifier is available in the /form/completions or /form/response API response.

Sample data
H_99999999 / E_99999999
layoutid string Query

Layout ID(if the form has custom layouts, then the use Get Form Fields API to get the layout ID) for custom PDF formatting. If not provided, uses default layout.

Sample response
{"linkExpiry":600,"status":1,"pdf":"{pdf link for the completion}"}
Dataset

Dataset APIs allow searching datasets, retrieving dataset records, and adding or updating dataset records by encrypted dataset and column identifiers.

List Datasets

Returns active company datasets with encrypted dataset and column identifiers that support API access.

Endpoint
GET /dataset
curl -X GET "https://www.bissafety.app/rest/v.01/dataset" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
searchText string Query

Optional search text to match dataset name or category name.

Sample response
{
  "datasets": [
    {
      "id": "_915778E00FF1C6EBE7F69EA599EFDCA",
      "name": "Employee Directory",
      "apiAccess": true,
      "category": {
        "value": "_ACF7631C827F1AB9C4CBF34C0D3223C",
        "label": "HR"
      },
      "columns": [
        {
          "id": "_5AFE7E5E459DEA7B5902F05694BF682F",
          "name": "employee_id",
          "unique": true
        },
        {
          "id": "_6F993159D2A77884F1F0AD837EA6AE61",
          "name": "firstname",
          "unique": false
        },
        {
          "id": "_7080EAC82B0CF785971A446766E38B934",
          "name": "city",
          "unique": false
        }
      ]
    }
  ]
}
Get Dataset Records

Returns dataset rows using encrypted dataset column IDs as keys. Requires dataset API access.

Endpoint
GET /dataset/records
curl -X GET "https://www.bissafety.app/rest/v.01/dataset/records?datasetId=_915778E00FF1C6EBE7F69EA599EFDCA" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
datasetId string Query required

Encrypted dataset ID returned by the List Datasets endpoint.

searchText string Query

Optional search text to filter records (if supported).

Sample response
{
  "rows": [
    {
      "_5AFE7E5E459DEA7B5902F05694BF682F": "1",
      "_6F993159D2A77884F1F0AD837EA6AE61": "Alice",
      "_7080EAC82B0CF785971A446766E38B934": "Toronto"
    },
    {
      "_5AFE7E5E459DEA7B5902F05694BF682F": "2",
      "_6F993159D2A77884F1F0AD837EA6AE61": "Bob",
      "_7080EAC82B0CF785971A446766E38B934": "Vancouver"
    }
  ]
}
Add Dataset Records

Adds or updates records in an existing dataset. This enpoint requires a datasetId query parameter and a JSON body with a records array. Records are identified by a unique column value; existing records are updated, new ones are added. Returns a summary with counts of added, updated, and skipped records, plus per-record status details.

Please note that the dataset must have a Unique column in order to use this endpoint. 

eg.

Unique Field Example

 

Endpoint
POST /dataset/records
curl -X POST "https://www.bissafety.app/rest/v.01/dataset/records?datasetId=_2ACF7631C827F1AB9C4CBF34C0D3223" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '[
  {
    "_5AFE7E5E459DEA7B5902F05694BF682F": "1",
    "_6F993159D2A77884F1F0AD837EA6AE61": "Alice",
    "_7080EAC82B0CF785971A446766E38B934": "Toronto"
  },
  {
    "_5AFE7E5E459DEA7B5902F05694BF682F": "2",
    "_6F993159D2A77884F1F0AD837EA6AE61": "Bob",
    "_7080EAC82B0CF785971A446766E38B934": "Vancouver"
  }
]'
Request parameters
datasetId string Query required

Dataset ID as returned by the List Datasets endpoint.

content-body json JSON body required

JSON array of records. Each key must be a dataset column ID as returned by List Datasets endpoint. Unique column must not have duplicate values.

Sample data
[
  {
    "_5AFE7E5E459DEA7B5902F05694BF682F": "1",
    "_6F993159D2A77884F1F0AD837EA6AE61": "Alice",
    "_7080EAC82B0CF785971A446766E38B934": "Toronto"
  }
]
Sample response
{
  "success": 1,
  "summary": {
    "added": 2,
    "updated": 0,
    "skipped": 0
  },
  "results": [
    {
      "status": "added",
      "message": "Record added."
    },
    {
      "status": "added",
      "message": "Record added."
    }
  ]
}
Delete Dataset Records

Deletes dataset rows whose unique-column value matches one of the supplied uniqueValues. Requires the dataset to have a unique column. Already-deleted or non-existent values return notFound in the per-value results; the call is idempotent and safe to retry.

Endpoint
DELETE /dataset/records
curl -X DELETE "https://www.bissafety.app/rest/v.01/dataset/records?datasetId=_2ACF7631C827F1AB9C4CBF34C0D3223" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
  "uniqueValues": ["1", "2"]
}'
Request parameters
datasetId string Query required

Encrypted dataset ID returned by the List Datasets endpoint.

content-body json JSON body required

JSON object body with a uniqueValues array. Each entry is matched against the dataset unique column value; matched active rows are deleted. Non-matching values return notFound in the response.

Sample data
{
  "uniqueValues": ["1", "2"]
}
Sample response
{
  "success": 1,
  "summary": {
    "deleted": 1,
    "notFound": 1,
    "skipped": 0
  },
  "results": [
    {
      "uniqueValue": "1",
      "status": "deleted",
      "message": "Record deleted."
    },
    {
      "uniqueValue": "2",
      "status": "notFound",
      "message": "No active record matched."
    }
  ]
}
Location

The company hierarchy refers to the structure in which your company organizes their employees, clients, customers, contractors, etc., which can be by location, sub location, department, or whichever way best meets your company's needs. 

List Locations

This API endpoint gets a list of all locations set up in company hierarchy in BIS Safety Software as shown in the Users tab and their corresponding information.

Endpoint
GET /location
curl -X GET "https://www.bissafety.app/rest/v.01/location" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies. By default, sub companies are not included "0".

Accepted values: 0 / 1

status string Query

A filter to get location with statuses: active, inactive. By default, the API returns active locations "A". If you want to get deactivated locations, use the parameter value "I". If you want to get both active and deactivated locations, leave the parameter value blank "". 

Accepted values: A / I / ""

Sample response
{
  "locations": [{
    "locationname": "Kicking Horse Canyon Construction",
    "locationcode": "KHCC",
    "status": "A",
    "parentlocation": "AIR EXTREME",
    "postalcode": "",
    "billto": "",
    "stateprov": "",
    "email": "",
    "subcompanyname": "In-House BIS",
    "city": "",
    "country": "",
    "maincontact": "",
    "address": "",
    "timezone": "",
    "website": "",
    "workphone": "",
    "custom field": "",
    "custom field 2": ""
  }]
}
Import Locations

You can add, update locations using this API endpoint.

Endpoint
POST /location
curl -X POST "https://www.bissafety.app/rest/v.01/location" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "locations=[{'locationname': 'Location 1', 'locationcode': 'Unique Code', 'status': 'A'}]"
Request parameters
locations json Form field required

This parameter is an array of location objects in JSON format. A maximum of 500 locations can be imported into BIS Safety Software at a time.

Sample data
{
  "locationname": "String - Required",
  "locationcode": "String - Recommended",
  "parentlocationname": "String - Optional",
  "parentlocationcode": "String - Optional",
  "postalcode": "String - Optional",
  "billto": "String - Optional",
  "stateprov": "String - Optional",
  "email": "String - Optional",
  "subcompanyname": "In-House BIS",
  "city": "String - Optional",
  "country": "String - Optional",
  "maincontact": "String - Optional",
  "address": "String - Optional",
  "timezone": "String - Optional - Value should be in time offset of UTC for example MST is -07:00",
  "website": "String - Optional",
  "workphone": "String - Optional",
  "status": "String Optional - Accepted value A and I"
}
Sample response
[
  {
    "locationname": "Location 1",
    "message": "Updated.",
    "error": 0,
    "locationcode": "Unique Code"
  }
]
Change Location Status

You can use this API endpoint will activate or deactivate a location.

Endpoint
POST /location/status
curl -X POST "https://www.bissafety.app/rest/v.01/location/status" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "locationname=LOCATION_NAME" \
-d "locationcode=LOCATION_CODE" \
-d "action=ACTION"
Request parameters
locationname string Form field

Name of the location. Required if locationcode is not passed.

locationcode string Form field

Code of the location. Required if locationname is not passed.

action string Form field required

Whether to activate or deactivate a location.

Accepted values: activate / deactivate

Sample response
{
  "status": "success",
  "message": "location was deactivated successfully"
}
Training Topic

Training topics are the requirements that user gets assigned by training matrix.

Topic Details

This API endpoint will return all training topics and courses mapped to them.

Endpoint
GET /topic/details
curl -X GET "https://www.bissafety.app/rest/v.01/topic/details?topicid=TopicID1,TopicID2" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
topicid string Query

Comma separated list of topic ids.

bisinternaltopicid string Query

One or more BIS topic numbers, separated by commas. This is the bisinternaltopicid returned by /topic/list. Use it for topics that have no topicid.

Sample response
{
  "topics": [{
    "topicname": "Safety Driving",
    "certificateprogram": 0,
    "topicid": "SD-100",
    "bisinternaltopicid": 90095,
    "levels": [{
      "fldlevel": 1,
      "levelname": 1,
      "itemsperlevel": 1,
      "hoursperlevel": "",
      "courses": [{
        "courseid": 28506161,
        "coursename": "AED/CPR Awareness Course",
        "hourspercourse": 1.00,
        "autoassign": false
      }]
    }]
  }, {
    "topicname": "Certification Program",
    "certificateprogram": 1,
    "topicid": "",
    "bisinternaltopicid": 90211,
    "levels": [{
      "fldlevel": 1,
      "levelname": "Level 1",
      "itemsperlevel": 1,
      "hoursperlevel": 1.00,
      "courses": [{
        "courseid": 37749623,
        "coursename": "Test Course",
        "hourspercourse": 1.50,
        "autoassign": false
      }]
    }]
  }]
}
Topic Assigned

This API endpoint will return all users and their assigned topics.

Endpoint
GET /topic/assigned
curl -X GET "https://www.bissafety.app/rest/v.01/topic/assigned" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software. 

bisinternaluserid numeric Query

System ID of a user in BIS.

topicid string Query

The unique topic ID for the training topic. 

bisinternaltopicid string Query

One or more BIS topic numbers, separated by commas. This is the bisinternaltopicid returned by /topic/list. Use it for topics that have no topicid.

Sample response
{
  "records": [{
    "topics": [
      {
        "topictype": "R",
        "topicid": "CSE-101",
        "bisinternaltopicid": 90095,
        "topic": "Confined Space Entry"
      },{
        "topictype": "O",
        "topicid": "",
        "bisinternaltopicid": 90211,
        "topic": "Working at Heights"
      }
    ],
    "employeeid": "1111",
    "lastname": "Doe",
    "firstname": "Jane",
    "bisinternaluserid": 123456
  }]
}
Topic Status

Returns the training topics each user is required to complete, with their completion status. The response is a list of users, each with a list of topics.

Topics an administrator has removed from one user are not returned. The same rules the user sees on their Training Matrix are applied: topic exceptions, location and role exceptions, the department setting, and the orientation and reactivation windows. A topic assigned directly to a named user is always returned, because an instruction about one person is more specific than a rule about a role.

topictype is R for required or O for optional. A user who holds the same topic as both gets two records, one of each, with the same completion status. bisinternaltopicid is the number BIS gives every topic and is always filled in; topicid is the ID your administrators type and can be empty.

Only current requirements are returned, so this endpoint cannot tell you that a topic stopped being required. /topic/status/delta reports that as a change, and returns only what changed since your last run.

assigneddate and duedate are returned only when you pass includeduedate=1, and are blank for certification programs. bisinternaluserid is returned only when you pass bisinternaluserid or includeuserwithoutuserid=1.

Endpoint
GET /topic/status
curl -X GET "https://www.bissafety.app/rest/v.01/topic/status" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software. 

bisinternaluserid numeric Query

System ID of a user in BIS.

topicid string Query

The topic ID your administrators type on the topic. Comma separated for more than one. It narrows the response to the topics you name; it does not change which topics qualify, so a topic removed by a topic exception is not returned either way.

offset numeric Query

Offset the results by a certain value. By default, the offset is zero "0". 

recordsperpage numeric Query

Limit the number of user and topic combinations returned up to a maximum of 500.

includeuserwithoutuserid numeric Query
Controls whether to include users without UserID set in the system. By Default, 0 = exclude users without UserIDs (default), 1 = include all users
includeduedate numeric Query
Controls whether to include topic assigned date and due date in response. This is only applicable for regular topics. Certification program type type does not support this functionality yet. By default the value is "0". 
bisinternaltopicid string Query

One or more BIS topic numbers, separated by commas. This is the bisinternaltopicid returned by /topic/list. Use it for topics that have no topicid.

Sample response
{
  "records": [{
    "topics": [{
      "status": "complete",
      "topictype": "R",
      "certificateprogram": 1,
      "topicid": "",
      "bisinternaltopicid": 90211,
      "topic": "Working at Heights",
      "completiondate": "YYYY-MM-DD",
      "expirydate": "YYYY-MM-DD",
      "assigneddate": "",
      "duedate": ""
    }, {
      "status": "incomplete",
      "topictype": "R",
      "certificateprogram": 0,
      "topicid": "CSE-101",
      "bisinternaltopicid": 90095,
      "topic": "Confined Space Entry",
      "completiondate": "YYYY-MM-DD",
      "expirydate": "YYYY-MM-DD",
      "assigneddate": "YYYY-MM-DD",
      "duedate": "YYYY-MM-DD"
    }],
    "employeeid": "1111",
    "bisinternaluserid": 123456,
    "lastname": "Doe",
    "firstname": "Jane"
  }]
}
Topic Reset

This API endpoint find all the completions that satisfies the topic for a user and archive those completions.

Endpoint
GET /topic/reset
curl -X GET "https://www.bissafety.app/rest/v.01/topic/reset?userid=USER_ID&topicid=TOPIC_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query required

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. This identifier, typically an employee ID or a system user ID, allows users' data to be correctly exchanged between your system and BIS Safety Software. 

topicid string Query

The topic ID your administrators type on the topic. Send either topicid or bisinternaltopicid.

bisinternaltopicid numeric Query

The BIS topic number, the bisinternaltopicid returned by /topic/list. Send either topicid or bisinternaltopicid. When both are sent, bisinternaltopicid is used.

Sample response
{
  "status": "success",
  "message": "Topic was reset successfully"
}
Topic List

Returns every training topic in your company with its IDs, without the courses and levels that /topic/details returns.

bisinternaltopicid is the number BIS gives every topic. It is always filled in and never repeats, so use it to refer to a topic in other calls. topicid is the ID your administrators type on the topic. It can be empty, and the same value can be typed on more than one topic.

Topics are returned in bisinternaltopicid order. count is the total number of topics. When offset plus recordsperpage is less than count, call again with a larger offset to get the next page.

Endpoint
GET /topic/list
curl -X GET "https://www.bissafety.app/rest/v.01/topic/list?offset=0&recordsperpage=500" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
offset numeric Query

Skip this many topics before the page starts. By default, the offset is zero "0".

recordsperpage numeric Query

How many topics one page returns. The default is 500 and the maximum is 10000.

Sample response
{
  "count": 2,
  "offset": 0,
  "recordsperpage": 500,
  "topics": [
    {
      "bisinternaltopicid": 90095,
      "topicid": "CSE-101",
      "topicname": "Confined Space Entry",
      "certificateprogram": 0
    },
    {
      "bisinternaltopicid": 90211,
      "topicid": "",
      "topicname": "Working at Heights",
      "certificateprogram": 1
    }
  ]
}
Topic Status Delta

Returns each user's training topics with the date each record last changed, so a scheduled job can ask for only what changed since its last run instead of reading every user and topic each time.

Leave lastupdateddate out and you get every topic each user holds now or held before. Send it and you get only the records that changed at or after that time, including topics that were taken away. A topic never assigned to a user is never returned.

assignmentstatus is assigned or unassigned. An unassigned record carries unassigneddate, has no topictype, and is your signal to drop the requirement; status, completiondate and expirydate are still filled in. One user and topic always produce one record, so a topic held as both required and optional is returned once, as R.

asof is the time this answer covers. Store it and send it back as the next lastupdateddate, exactly as received. It is set fifteen minutes before the call so that records saved a little late are not skipped, which means a change made in the last fifteen minutes arrives on the next run.

Pages are read with cursor, not offset. Send nextcursor back until it comes back empty; every page of one run carries the same asof. Match records on bisinternaluserid and bisinternaltopicid, and apply each record by replacing what you hold, because the same record can arrive more than once.

Expiry, deleted topics and deactivated users are not sent as changes. Treat a record whose expirydate has passed as expired, and take a full copy from time to time to drop anything that no longer appears in it.

Endpoint
GET /topic/status/delta
curl -X GET "https://www.bissafety.app/rest/v.01/topic/status/delta?lastupdateddate=2026-07-30T00:00:00Z&recordsperpage=500&includecount=1" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
lastupdateddate string Query

Returns only the records that changed at or after this date and time, in ISO format (YYYY-MM-DDTHH:MM:SSZ). Times are UTC. Send back the asof value from your previous run. Leave it blank to get every record.

Sample data
2026-07-30T00:00:00Z
cursor string Query

Pagination token. Leave it blank on the first call, then send back the nextcursor value from the previous response until it comes back empty. A blank value starts from the beginning.

Sample data
38893_90095_1785456251
userid string Query

The User ID is a unique and consistent identifier for each user in your system that is also used as a common identifier for the same users in BIS Safety Software. To get multiple users, you can pass User ID as comma separated list.

bisinternaluserid numeric Query

System ID of a user in BIS. Comma separated for more than one.

topicid string Query

The topic ID your administrators type on the topic. Comma separated for more than one. It can be empty and the same value can be used by more than one topic, so identify topics by bisinternaltopicid in the response.

bisinternaltopicid numeric Query

The number BIS gives every topic, returned as bisinternaltopicid and also available from /topic/list. Comma separated for more than one. Unlike topicid it is always filled in, so use it to ask about a particular topic.

includeoptional numeric Query

Set to 0 to leave out topics a user holds only as optional. A topic is required when any one of the user's assignments makes it required. Topics the user no longer holds are always returned.

Accepted values: 1 / 0

includeuserwithoutuserid numeric Query

Controls whether to include users without UserID set in the system. Ignored when the request filters by bisinternaluserid.

Accepted values: 0 / 1

includecount numeric Query

Set to 1 to include count, the total number of records in this run. It is worked out only on the first call and is ignored when cursor is supplied.

Accepted values: 0 / 1

recordsperpage numeric Query

Limit the number of user and topic records that are returned up to a maximum of 10000.

Sample response
{
  "mode": "delta",
  "recordsperpage": 500,
  "count": 1284,
  "nextcursor": "38893_90095_1785456251",
  "asof": "2026-07-31T09:24:11Z",
  "records": [
    {
      "employeeid": "E10432",
      "bisinternaluserid": 38893,
      "firstname": "Jane",
      "lastname": "Doe",
      "topics": [
        {
          "topic": "Confined Space Entry",
          "topicid": "CSE-101",
          "bisinternaltopicid": 90095,
          "status": "complete",
          "completiondate": "2026-03-14",
          "expirydate": "2027-03-14",
          "topictype": "R",
          "certificateprogram": 0,
          "assignmentstatus": "assigned",
          "unassigneddate": "",
          "modifiedon": "2026-07-29T18:04:11Z"
        },
        {
          "topic": "Working at Heights",
          "topicid": "WAH-200",
          "bisinternaltopicid": 90211,
          "status": "incomplete",
          "completiondate": "",
          "expirydate": "",
          "certificateprogram": 0,
          "assignmentstatus": "unassigned",
          "unassigneddate": "2026-07-29",
          "modifiedon": "2026-07-29T18:04:11Z"
        }
      ]
    }
  ]
}
Roles

This API endpoint gets company roles.

Endpoint
GET /role
curl -X GET "https://www.bissafety.app/rest/v.01/role" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies. By default, sub companies are not included "0".

Accepted values: 0 / 1

Sample response
{
  "roles": [{
    "role": "Test a role",
    "rolecode": "0023",
    "company": "In-House BIS"
  }, {
    "role": "Company Sanctioned Driver",
    "rolecode": "",
    "company": "In-House BIS"
  }]
}
Task

Users can be assigned tasks from the task module and from within Task Assignment field in digital forms.

Get Tasks

This endpoint can be used to fetch all tasks in the system.

Endpoint
GET /task
curl -X GET "https://www.bissafety.app/rest/v.01/task" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
taskstatus string Query

Returns all tasks with specified task status. If no task status is provided, then all pending tasks are returned.

Accepted values: Pending / Overdue / Completed / All

location string Query

Returns all tasks that are associated with the provided location. If no location is provided, then all tasks are returned.

includearchived numeric Query

If this is set to 1, then all tasks that were assigned by archived forms will also be included in the response.

Accepted values: 0 / 1

fromdate date Query

All tasks that were added from the provided date in the date format (YYYY-MM-DD) are returned. If the fromdate and todate parameters are left blank, all tasks are returned.

todate date Query

All tasks that were added until the provided date in the date format (YYYY-MM-DD) are returned. If the fromdate and todate parameters are left blank, all tasks are returned.

taskid numeric Query

Returns the task with this task ID. When this parameter is provided, the taskstatus and includearchived parameters are ignored, so a completed task, or a task from an archived form, is still returned. Inactive tasks are never returned.

An ID that is not a positive whole number returns the error "Invalid Task ID Provided".

Sample data
145247
completionid string Query

Returns all tasks created by this form completion. Use the completionid returned by the Get Form Data and Get Completions endpoints, in the format "H_{id}" or "E_{id}" (you can only provide one ID per request).

When this parameter is provided, the taskstatus and includearchived parameters are ignored, so completed tasks are included. Inactive tasks, and follow-up forms assigned from a task field, are not returned.

An ID in any other format returns the error "Invalid Completion ID Provided".

Sample data
H_99999999 / E_99999999
Sample response
{
  "tasks": [
    {
      "location": "Corporate Head Office (BIS)",
      "dateadded": "2023-10-25",
      "datecompleted": "2023-10-25",
      "eventId": "",
      "formID": 30411,
      "formTitle": "*Hazard Assessment",
      "taskname": "Hazards Test",
      "taskProof": "/assets/TaskVisualProof/1/Signature_136594CE-B0DC-8CAB-10E1539C32F667asd.jpg",
      "taskid": 145247,
      "equipmentID": "",
      "completionid": "H_985476",
      "status": "completed",
      "TaskComment": "Task completed",
      "description": "Please test the all hazards",
      "archive": 0,
      "requireVisualProof": 0,
      "taskLocation": "",
      "userid": "B0001285",
      "username": "Austin Gonzales (AGonzales86 - Corporate Head Office (BIS))",
      "addedbyusername": "Austin Gonzales",
      "duedate": "2023-10-25",
      "overdue": ""
    },
    {
      "location": "Corporate Head Office (BIS)",
      "dateadded": "2019-12-03",
      "datecompleted": "2021-09-24",
      "eventId": "",
      "formID": 3641,
      "formTitle": "Task Lock Date Test",
      "taskname": "Complete Inspection",
      "taskProof": "",
      "taskid": 4487,
      "equipmentID": 898,
      "completionid": "E_123456",
      "status": "completed",
      "TaskComment": "This task has been closed.",
      "description": "",
      "archive": 0,
      "requireVisualProof": 0,
      "taskLocation": "",
      "userid": "1111",
      "username": "Aswathy S (as1 - Corporate Head Office (BIS))",
      "addedbyusername": "Aswathy S",
      "duedate": "2019-12-03",
      "overdue": ""
    }
  ],
  "totalTasks": 2
}
E-Commerce

API endpoints related to company's E-commerce store.

Get Available Products

This API gets the courses and products in the company's e-commerce store.

launchcode is not returned by default. Contact your account manager to have it included.

Endpoint
GET /products
curl -X GET "https://www.bissafety.app/rest/v.01/products" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
types string Query

The type of content in the e-Commerce store. The data returned from this API will show either online courses only "Online" or online courses, classroom courses, and physical products "All". 

Accepted values: Online / All

Sample response
{
  "itemCount": 1422,
  "redirectUrl": "",
  "items": [{
    "price": 79.95,
    "video": "Video_Link",
    "ratingcount": 22,
    "portrait": "Image_Link",
    "expanded": "",
    "productID": "12-steps-to-establishing-leadership-presence-fuel-navigate-drive",
    "name": "12 Steps to Establishing Leadership Presence",
    "short": "SHORT DESCRIPTION",
    "thumnail": "Image_Link",
    "rating": 4.4,
    "large": "Image_Link",
    "altname": "",
    "type": 9,
    "long": "LONG DESCRIPTION",
    "launchcode": "LAUNCH CODE for SSO"
  }, {
    "price": 249.95,
    "video": "Video_Link",
    "ratingcount": "",
    "portrait": "Image_Link",
    "expanded": "",
    "productID": "5-minute-fundamentals-dvd",
    "name": "5 Minute Fundamentals DVD",
    "short": "SHORT DESCRIPTION",
    "thumnail": "Image_Link",
    "rating": "",
    "large": "Image_Link",
    "altname": "",
    "type": 8,
    "long": "LONG DESCRIPTION",
    "launchcode": "LAUNCH CODE for SSO"
  }]
}
Asset

Asset API endpoints let API clients read category metadata, list/create/update assets, and manage asset documents and required documents. All calls require a valid Bearer token.

Get Asset Categories

Returns asset categories configured for the authenticated company, including type/status options, enabled fields, custom fields, and required-document settings used by the Asset UI and integrations.

Endpoint
GET /asset/categories
curl -X GET "https://www.bissafety.app/rest/v.01/asset/categories" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Sample response
{
  "assetTypes": [
    {
      "categoryID": "CATEGORY_ID",
      "name": "Location",
      "displayName": "Location",
      "isLocation": true,
      "isDisabled": false,
      "types": [
        {
          "id": "TYPE_ID",
          "name": "Forklift",
          "colorCode": "#f1f1f1",
          "active": true
        },
        {
          "id": "TYPE_ID",
          "name": "Crane",
          "colorCode": "#00ff90",
          "active": true
        }
      ],
      "statuses": [
        {
          "id": "STATUS_ID",
          "name": "In Service",
          "colorCode": "#d31717",
          "active": true
        },
        {
          "id": "STATUS_ID",
          "name": "Out of Service",
          "colorCode": "#b34242",
          "active": true
        }
      ],
      "enabledFields": [
        {
          "id": "FIELD_ID",
          "field": "type",
          "name": "Type",
          "active": true
        },
        {
          "id": "FIELD_ID",
          "field": "serialNumber",
          "name": "Serial Number",
          "active": true
        }
      ],
      "customFields": [
        {
          "id": "FIELD_ID",
          "name": "test",
          "type": "textfield",
          "active": true,
          "defaultChoice": 0
        }
      ],
      "requiredDocumentSettings": {
        "enabled": true,
        "complianceTarget": 99.99,
        "documentTypes": [
          {
            "documentTypeId": "REQUIRED_DOCUMENT_TYPE_ID",
            "name": "MR TEST",
            "hasExpiry": false,
            "needApproval": false
          },
          {
            "documentTypeId": "REQUIRED_DOCUMENT_TYPE_ID",
            "name": "MR test10",
            "hasExpiry": true,
            "needApproval": true
          }
        ]
      }
    },
    {
      "categoryID": "CATEGORY_ID",
      "name": "Assets",
      "displayName": "Equipment",
      "isLocation": false,
      "isDisabled": false,
      "types": [],
      "statuses": [],
      "enabledFields": [],
      "customFields": [],
      "requiredDocumentSettings": {
        "enabled": false,
        "complianceTarget": 0,
        "documentTypes": []
      }
    }
  ]
}
List Assets

Returns paginated assets for the authenticated company with optional filters (asset/category/status/type/location/serial/search), active-state filtering, and sorting.

Endpoint
GET /asset
curl -X GET "https://www.bissafety.app/rest/v.01/asset?categoryid=CATEGORY_ID&search=&active=A&offset=0&recordsperpage=50" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
assetid string Query

Asset id. When provided, response is limited to that asset.

serialnumber string Query

Exact serial number filter (active company assets only).

categoryid string Query

Asset category id filter.

statusid string Query

Status id filter. Empty/0 means no status filtering.

typeid string Query

Type id filter. Empty/0 means no type filtering.

locationid string Query

Location id filter. Empty/0 means no location filtering.

search string Query

Case-insensitive text search across name, serial number, manufacturer, model, description, and current site.

active string Query

Asset state filter: A (active, default) or I (inactive). Any value other than I is treated as active.

Sample data
A
offset numeric Query

Pagination offset (0-based).

Sample data
0
recordsperpage numeric Query

Page size. Values are clamped to 1..500 on the server. Default is 50.

Sample data
50
orderby string Query

Sort column key: name, location, serialNumber, or description. Any other value defaults to name.

sortdirection string Query

Sort direction: ASC or DESC. Any non-DESC value defaults to ASC.

Sample data
ASC
Sample response
{
  "assets": [
    {
      "active": true,
      "assetId": "ASSET_ID",
      "categoryId": "CATEGORY_ID",
      "currentSite": "",
      "description": "",
      "hours": "5",
      "locationId": "LOCATION_ID",
      "locationName": "corporate Head office (BIS)",
      "manufacturer": "",
      "mileage": "10",
      "model": "",
      "name": "12544 test asset",
      "serialNumber": "",
      "statusId": null,
      "statusName": "",
      "typeId": null,
      "typeName": ""
    }
  ],
  "offset": 0,
  "recordsPerPage": 50,
  "totalCount": 8
}
Save Asset

Creates or updates an asset using JSON body data. Update flow uses assetid or serialnumber; create flow uses categoryid. Returns assetId on create or success=true on update. Returns 400 for invalid payload/inputs and 404 when serialnumber lookup does not resolve to a single active asset.

When you pass only categoryid, a new asset is created and the response is {"assetId": "ASSET_ID"}. When you pass assetid or serialnumber, that asset is updated and the response is {"success": true}.

Endpoint
POST /asset
curl -X POST "https://www.bissafety.app/rest/v.01/asset?categoryid=CATEGORY_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
  "name": "Test Asset",
  "locationId": "LOCATION_ID",
  "serialNumber": "SN-0011",
  "description": "Description for Test Asset",
  "customFields": {
    "TEXT_CUSTOM_FIELD_ID": "Sample text value",
    "DATE_CUSTOM_FIELD_ID": "2026-12-31",
    "MULTIPLE_CHOICE_CUSTOM_FIELD_ID": "OPTION_ID",
    "MULTISELECT_CUSTOM_FIELD_ID": ["OPTION_A_ID", "OPTION_B_ID"]
  }
}'
Request parameters
assetid string Query

Asset ID of the asset to update (from GET /asset endpoint). If present and valid, API updates that asset.

serialnumber string Query

Serial number lookup for update flow. Must resolve to exactly one active asset in the company.

categoryid string Query

Category id for create flow.

content-body json JSON body required

Required JSON object body. For create, name is required by service validation. Common fields: name, serialNumber, description, locationId, statusId, typeId, manufacturer, model, currentSite, hours, mileage.

Custom fields: category-specific custom field values are supplied in an optional customFields object within this same body. Each key is the encrypted custom field id returned by GET /asset/categories (the matching category's customFields[].id). The value format depends on that field's type:

  • textfield – a plain text string.
  • datefield – a date string; stored as YYYY-MM-DD. Values that are not valid dates are ignored.
  • multiplechoice – the encrypted optionId of the selected option, taken from that field's options[].optionId in GET /asset/categories.
  • multiselect – an array of the selected options' optionText values (a single text string is also accepted).

Call GET /asset/categories to discover a category's custom fields, their type, and the available option ids/text. Options that cannot be matched are skipped and reported back in the response message array.

Sample data
{
  "name": "Test Asset",
  "serialNumber": "SN-0011",
  "description": "Description for Test Asset",
  "locationId": "LOCATION_ID",
  "customFields": {
    "TEXT_CUSTOM_FIELD_ID": "Sample text value",
    "DATE_CUSTOM_FIELD_ID": "2026-12-31",
    "MULTIPLE_CHOICE_CUSTOM_FIELD_ID": "OPTION_ID",
    "MULTISELECT_CUSTOM_FIELD_ID": ["OPTION_A_ID", "OPTION_B_ID"]
  }
}
Sample response
{
  "assetId": "ASSET_ID"
}
Get Asset Required Documents

Returns required-document uploads for a resolved asset (assetid or serialnumber) with controls for archive and expired-document visibility. Includes approval status, expiry, download link, and computed document status.

Endpoint
GET /asset/requiredDocuments
curl -X GET "https://www.bissafety.app/rest/v.01/asset/requiredDocuments?assetid=ASSET_ID&includearchived=1&includeexpireddocuments=1" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
assetid string Query

Asset ID of the asset whose required documents you want to retrieve. Either assetid or serialnumber is required.

serialnumber string Query

Serial number of the asset whose required documents you want to retrieve. Either assetid or serialnumber is required.

includearchived numeric Query

Archive toggle: 0 active-only (default), 1 include archived.

Sample data
0
includeexpireddocuments numeric Query

Expiry toggle: 0 exclude expired (default), 1 include expired.

Sample data
0
Sample response
{
  "requiredDocuments": [
    {
      "documentId": "REQUIRED_DOCUMENT_ID",
      "title": "License",
      "documentName": "Operator License",
      "uploadedBy": "API",
      "uploadDate": "2026-01-10 12:00:00",
      "approvalStatus": "Approved",
      "expiryDate": "2026-12-31",
      "docPath": "https://example.com/v1/index.cfm?action=learner.downloadFilePublic&type=_asset_required_document_token&id=REQUIRED_DOCUMENT_ID",
      "documentStatus": "active"
    },
    {
      "documentId": "REQUIRED_DOCUMENT_ID",
      "title": "Inspection",
      "documentName": "Quarterly Inspection",
      "uploadedBy": "Jane Doe",
      "uploadDate": "2026-03-01 09:20:00",
      "approvalStatus": "Pending",
      "expiryDate": "",
      "docPath": "https://example.com/v1/index.cfm?action=learner.downloadFilePublic&type=_asset_required_document_token&id=REQUIRED_DOCUMENT_ID",
      "documentStatus": "active"
    }
  ]
}
Add Asset Required Document

Uploads a required-document file for an asset using documenttypeid. Existing active Pending/Denied records of the same required-document type are archived before insert; new API upload is stored as Approved.

Endpoint
POST /asset/requiredDocument
curl -X POST "https://www.bissafety.app/rest/v.01/asset/requiredDocument" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-F "assetid=ASSET_ID" \
-F "serialnumber=SN-123" \
-F "documenttypeid=REQUIRED_DOCUMENT_TYPE_ID" \
-F "documentname=Operator License" \
-F "expirydate=2026-12-31" \
-F "file=@/path/to/document.pdf"
Request parameters
assetid string Form field

Asset ID of the asset to which the required document will be uploaded. Either assetid or serialnumber is required.

serialnumber string Form field

Serial number of the asset to which the required document will be uploaded. Either assetid or serialnumber is required.

documenttypeid string Form field required

Required-document type id. Mandatory for upload.

documentname string Form field

Optional display name for uploaded required document.

Sample data
Operator License
expirydate string Form field

Optional expiry date. If provided, use YYYY-MM-DD.

Sample data
2026-12-31
file file File required

Required upload file. Allowed types: jpeg, jpg, png, pdf, xlsx, xls, docx, doc.

Sample response
{
  "documentId": "REQUIRED_DOCUMENT_ID",
  "message": "Required document Operator License added"
}
Delete Required Document

Archives an active required-document record by requiredDocumentId and returns success=true with a status message. This endpoint uses HTTP DELETE and expects requiredDocumentId in the query string.

Endpoint
DELETE /asset/requiredDocument
curl -X DELETE "https://www.bissafety.app/rest/v.01/asset/requiredDocument?requiredDocumentId=REQUIRED_DOCUMENT_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
requiredDocumentId string Query required

Required-document id to archive. Sent in the query string.

Sample response
{
  "success": true,
  "message": "Document Operator License archived."
}
Get Asset Documents

Returns uploaded asset documents for a resolved asset (assetid or serialnumber), with archive inclusion, search, and sorting. Returns 400 when asset reference is missing and 404 when the target asset cannot be resolved.

Endpoint
GET /asset/documents
curl -X GET "https://www.bissafety.app/rest/v.01/asset/documents?assetid=ASSET_ID&includearchived=0&sortcolumn=docname&sortdirection=ASC" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
assetid string Query

Asset ID of the asset whose documents you want to retrieve. Either assetid or serialnumber is required.

serialnumber string Query

Serial number of the asset whose documents you want to retrieve. Either assetid or serialnumber is required.

includearchived numeric Query

Archive toggle: 0 active-only (default), 1 include archived.

Sample data
0
search string Query

Free-text match against document name and uploader full name.

sortcolumn string Query

Sort key: docname or addeddate. Any other value defaults to docname.

Sample data
docname
sortdirection string Query

Sort direction: ASC or DESC. Empty defaults to ASC; any non-ASC value is treated as DESC.

Sample data
ASC
Sample response
{
  "documents": [
    {
      "documentId": "DOCUMENT_ID",
      "docName": "Inspection Form.pdf",
      "docType": "pdf",
      "docPath": "https://example.com/v1/index.cfm?action=learner.downloadFilePublic&type=_asset_document_token&id=DOCUMENT_ID",
      "addedDate": "2026-01-10 12:00:00",
      "expiryDate": "2026-12-31",
      "active": true,
      "uploadedBy": "API"
    },
    {
      "documentId": "DOCUMENT_ID",
      "docName": "Service Log.xlsx",
      "docType": "xlsx",
      "docPath": "https://example.com/v1/index.cfm?action=learner.downloadFilePublic&type=_asset_document_token&id=DOCUMENT_ID",
      "addedDate": "2026-02-22 10:30:45",
      "expiryDate": "",
      "active": true,
      "uploadedBy": "John Smith"
    }
  ]
}
Add Asset Document

Uploads a document file and links it to an asset (assetid or serialnumber). File is required and allowed file types are jpeg/jpg/png/pdf/xlsx/xls/docx/doc. Duplicate active names are auto-adjusted to a unique name.

Endpoint
POST /asset/documents
curl -X POST "https://www.bissafety.app/rest/v.01/asset/documents" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-F "assetid=ASSET_ID" \
-F "serialnumber=SN-123" \
-F "documentname=Test Document" \
-F "expirydate=2026-12-31" \
-F "file=@/path/to/document.pdf"
Request parameters
assetid string Form field

Asset ID of the asset to which the document will be uploaded. Either assetid or serialnumber is required.

serialnumber string Form field

Serial number of the asset to which the document will be uploaded. Either assetid or serialnumber is required.

documentname string Form field required

Display name for saved document. Server appends uploaded extension and auto-deduplicates active names if needed.

Sample data
Test Document
expirydate string Form field

Optional expiry date. If provided, use YYYY-MM-DD.

Sample data
2026-12-31
file file File required

Required upload file. Allowed types: jpeg, jpg, png, pdf, xlsx, xls, docx, doc.

Sample response
{
  "added": 1,
  "message": "Document added: Test Document.pdf"
}
Update Asset Document

Updates existing asset document metadata (name and/or expiry date). Returns success=true on success. Returns 400 if the encrypted document id is invalid or the document cannot be updated.

Endpoint
POST /asset/documents/update
curl -X POST "https://www.bissafety.app/rest/v.01/asset/documents/update" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-F "documentid=DOCUMENT_ID" \
-F "documentname=Updated Title" \
-F "expirydate=2027-01-15"
Request parameters
documentid string Form field required

Document id to modify.

documentname string Form field

Optional new document title.

Sample data
Updated Title
expirydate string Form field

Optional new expiry date in YYYY-MM-DD format.

Sample data
2027-01-15
Sample response
{
  "success": true
}
Delete Asset Document

Soft-archives an asset document by documentid and returns success=true. This endpoint uses HTTP DELETE and expects documentid in the query string.

Endpoint
DELETE /asset/documents
curl -X DELETE "https://www.bissafety.app/rest/v.01/asset/documents?documentid=DOCUMENT_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
documentid string Query required

Document id to archive (soft delete). Sent in the query string.

Sample response
{
  "success": true
}
Classroom Event

There are three API endpoints to get and update classroom events.

List Events

This API endpoint gets all classroom calendar events.

Endpoint
GET /event
curl -X GET "https://www.bissafety.app/rest/v.01/event" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
fromdate date Query

All events in the classroom calendar scheduled on or after the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are left blank, all classroom events are returned. 

todate date Query

All events in the classroom calendar scheduled on or before the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are left blank, all classroom events are returned. 

status string Query

A filter to active events. By default, the API returns all active/deactivated events. If you want only active events, the parameter value "A". If you want to get both active and deactivated events, leave the parameter value empty or exclude the parameter.

Accepted values: A / ""

courseid string Query

The course ID for the calendar event.

modified date Query

All events in the classroom calendar that was modified after the date(yyyy-mm-dd format) will be returned.

Sample response
{
  "events": [{
    "location": "CITY",
    "starttime": "08:00AM",
    "startdate": "YYYY-MM-DD",
    "eventid": "EVENT_ID",
    "courseid": "COURSE_ID",
    "course": "COURSE_NAME",
    "courselink": "LINK_TO_THE_EVENT_REGISTER_PAGE",
    "priceDetails": {
      "default": 150.00,
      "membership": [
        {
          "id": "1234567890",
          "name": "Member Tier",
          "price": 120.00
        }
      ]
    },
    "policy": "Cancellation policy text.",
    "internalcourseid": "COURSE_ID",
    "capacity": 20,
    "requirements": {
      "participant": "Participant requirement details.",
      "instructor": ""
    },
    "duration": {
      "days": 1,
      "schedule": [
        {
          "date": "2016-07-21",
          "end": "12:00 PM",
          "start": "08:30 AM"
        }
      ]
    }
  }]
}
Get Event Participants

This API endpoint gets all classroom event participants.

Endpoint
GET /event/participants
curl -X GET "https://www.bissafety.app/rest/v.01/event/participants" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
fromdate date Query

All event participants in the classroom calendar scheduled on or after the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are left blank, all classroom event participants are returned.

todate date Query

All event participants in the classroom calendar scheduled on or before the provided date in the date format (YYYY-MM-DD). If the fromdate and todate parameters are left blank, all events participants are returned.

onlynotapproved numeric Query

All event participants that have not been approved yet. If notonlyapproved is left blank, then all participants are returned.

Accepted values: 0 / 1

courseid string Query

The course ID set up for the online course and specific to each company.

coursename string Query

The course ID for the calendar event.

eventid numeric Query

System event ID where new participants will be created.

includeallparticipants numeric Query

This parameter is used to include all participants including inactive participants in the response.

Accepted values: 0 / 1

Sample response
{
    "success": true,
    "participants": [
        {
            "initials": "AD",
            "startdate": "2022-09-14",
            "firstname": "Aaron",
            "courseid": 37913732,
            "coursename": "First Aid",
            "eventid": 72783,
            "birthdate": "1999-05-18",
            "locationcode": 10,
            "enddate": "2022-10-2002",
            "locationname": "Classroom Registrants",
            "status": "Failed",
            "participantid": 621781,
            "lastname": "Duclos",
            "userid": "B0001232",
            "gender": "Female",
            "sin": "678355411",
            "participantlastupdated": "2022-09-21",
            "registrationstatus": "Active"
        },
        {
            "initials": "AD",
            "startdate": "2022-09-14",
            "firstname": "Adam",
            "courseid": 37913732,
            "coursename": "First Aid",
            "eventid": 72783,
            "birthdate": "",
            "locationcode": 10487,
            "enddate": "2022-10-2002",
            "locationname": "Classroom Registrants",
            "status": "NotStarted",
            "participantid": 324205,
            "lastname": "Doe",
            "userid": "BIS0001645",
            "gender": "Male",
            "sin": "678355412",
            "participantlastupdated": "2022-09-21",
            "registrationstatus": "Inactive"
        }
    ]
}
Patch Event Participants

This API endpoint can be used to patch event participants.

Endpoint
PATCH /event/participants
curl -X PATCH "https://www.bissafety.app/rest/v.01/event/participants" \
   -H "Authorization: Bearer YOUR_BEARER_TOKEN" \
   -H "Content-Type: application/json" \
   -d '[
         {
           "participantid": 621781,
           "status": "pass",
           "expiry": "2024-06-27",
           "approved": 1,
           "mark": 80
         },
         {
           "participantid": 621782,
           "status": "fail"
         }
      ]'
Request parameters
content-body json JSON body required

A JSON object structure (field and and value combination) to update the participants' statuses.

  • participantid - A unique id to identify participants for classroom calendar events. participantid is required in JSON. If it is not provided, the response will return error for this participant and then move to the next element in the array.
  • status - Status indicates if the participant passed or failed the course. It is also required. If it is not provided, the response will return error for this participant and then move to the next element in the array. The system only accepts the following values for status:
    • Pass
    • Fail
    • Absent
  • expiry - Expiry is the expiry date for the record created for the participant. If expiry is not provided, the system takes the course expiry as expiry date.
  • approved - Approved indicates whether the participant was approved or not. If it is not provided, the participant is automatically approved if the status was pass. Otherwise, the participant is not approved. Accepted values are (1/0) 1 = Approved| 0 = Not approved.
  • mark - Mark indicates what marks participant recieved for the event. If it is not provided and the participant passed the course, the mark is automatically set to 100 for the participant. Otherwise, it is 0. Accepted values are between 0 and 100.
Sample data
[
    {
        "participantid": "String - Required - Unique participantid to identify participant",
        "status": "String - Required - Accepted value pass/fail/absent",
        "expiry": "Date - Optional - Date YYYY-MM-DD format",
        "approved": "Numeric - Optional - Accepted value 0/1",
        "mark": "Numeric - Optional - Accepted value between 0 and 100"
    }
]
Sample response
{
    "success": 1,
    "participantData": [
        {
            "success": 1,
            "id": 621781
        },
        {
            "success": 1,
            "id": 621782
        }
    ]
}
Add Event Participants

This API endpoint can be used to add new event participants.

Endpoint
POST /event/participants
curl -X POST "https://www.bissafety.app/rest/v.01/event/participants" \
   -H "Authorization: Bearer YOUR_BEARER_TOKEN" \
   -H "Content-Type: application/x-www-form-urlencoded" \
   -d 'eventid=137142' \
   -d 'participants=[
         {
           "userid": 621781
         },
         {
           "userid": 621782
         }
      ]'
Request parameters
eventid string Form field required

System event ID where new participants will be created. Event ID can encrypted or decrypted.

allowmultireg numeric Form field

Allow participants to be added to be registered for multiple events for the same course.

Accepted values: 0 / 1

Sample response
{
    "success": 1,
    "eventid": "137142",
    "participants": [
        {
            "success": 1,
            "userid": "BIS0001605"
        },
        {
            "success": 0,
            "userid": "BIS0001367",
            "error": "event_full",
            "error_description": "Classroom event is full"
        }
    ]
}
Webhooks

Webhook functionality that allows external systems to receive real-time notifications about specific events within the BIS Safety Software platform.

Course Completion Event Hook

In addition to APIs, BIS also uses event hooks, which are outgoing calls from BIS Safety Software that trigger processes in your system's software. The event hook will push course completions from BIS Safety Software to your system with a POST request.

Contact your account manager to register for this event hook. To set up an event hook, you need to implement an API endpoint in your system that is external to BIS Safety Software and accepts our server's POST request whenever one or more courses are completed by users in your BIS Safety Software portal. BIS requires a long term bearer token from you, which is implemented in BIS Safety Software and used in an Authorization header so your system can verify our POST requests.

You can get course completion pushes by selecting specific courses or all courses completed by your users in BIS Safety Software. The selected courses should have course codes set up and users should have user IDs set up in BIS Safety Software in order for the event hook to push course completions. 

The POST request sends the form fields listed below.

Your API must handle multiple POST requests for the same course completion ID. If your system already saved the completion ID, then your system must update that completion ID with updated scores, results, and completiondates from any following requests as our system may send multiple calls for the same course completion.

Endpoint
POST https://your-endpoint
curl -X POST "https://your-endpoint" \
-H "Authorization: Bearer PROVIDED_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "completionid=COMPLETION_ID" \
-d "userid=USERID" \
-d "bisinternaluserid=BIS_USER_ID" \
-d "bisinternalcourseid=BIS_COURSE_ID" \
-d "coursecode=COURSE_CODE" \
-d "score=SCORE" \
-d "result=1" \
-d "completiondate=YYYY-MM-DD HH:MM:SS" \
-d "expirydate=EXPIRY_DATE"
Request parameters
completionid numeric Form field required

The course completion ID. BIS may send the same completion more than once; update the record you already saved.

userid string Form field required

The user ID (employee ID) of the user who completed the course.

bisinternaluserid numeric Form field required

The user's ID in BIS Safety Software.

bisinternalcourseid numeric Form field required

The course's ID in BIS Safety Software.

coursecode string Form field required

Your course code for the course. Empty when the course has no course code.

score string Form field required

The final course mark, with two decimal places.

result numeric Form field required

1 = pass, 0 = fail.

completiondate string Form field required

When the course was completed, as YYYY-MM-DD HH:MM:SS.

expirydate string Form field required

When the completion expires. Empty when it does not expire.

Single Sign-On (SSO)

SSO is a user/session authentication service that allows a user to use one set of login credentials to access multiple applications.

BIS Safety Software allows for SSO access from any web-based system that can authenticate the user via a username or email and the password. This may include a legacy Learning Management System, a payroll system, or a company intranet portal that requires users to log in. The SSO link can be embedded within any button the user clicks to access their company portal. The SSO link bypasses the BIS Safety Software login screen and takes users straight to their homepage.

SSO Functionality

There are several features built into the SSO service:

  • Creation of a new account: New accounts are created for any new users as soon as they click the SSO link.
  • Access to existing accounts: If users already exist in the system, and they are confirmed by a unique identifier, the system redirects the users to their existing accounts.
  • Adding courses: The SSO service can automatically add courses to existing or new accounts by providing "Course ID" with SSO requests. 
  • Automatic user provisioning: User accounts are automatically added, updated, and deactivated based on changes in your Azure active directory.

 

SAML 2.0 SSO

We support Security Assertion Markup Language (SAML) 2.0 single sign-on. Our system can act as an application service provider (SP) and use your organization's identity provider to authorize and allow user access to our system.

If you are using Microsoft Azure, you can use the tutorial at https://docs.microsoft.com/en-us/azure/active-directory/saas-apps/bis-tutorial to set up your SSO. Client admins can download SP metadata file from your Portal Settings page -> Integrations -> SSO Section. Use this file to complete setting up the Azure SSO App.

After the Azure app is setup, upload the Federation(Identity Provider) metadata XML file to Portal Settings page -> Integrations -> SSO Section to complete integration.

User Provisioning

Our SSO allows for automatic user provisioning with Microsoft Entra ID (formerly known as Microsoft Azure AD). Our system will use your organization’s Entra ID to create, update, and deactivate user accounts as the roles of users change in your organization. 

You must have access to an Entra ID tenant and have the permissions to configure provisioning in your Entra ID. You can use this tutorial at https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/bis-provisioning-tutorial to set up automatic user provisioning. Please contact us to get your credentials for authorization. 

Custom SSO

BIS provides a custom SSO for companies who do not support SAML 2.0 SSO. Setting up a custom SSO requires a bit of coding to set up. You can follow the guidelines below to help you.

  1. Follow the instructions in the Authentication section above to obtain a bearer token using the secret BIS Safety Software API credentials provided by BIS Account Managers. 
  2. The API accepts user parameters as JSON objects.
  3. Upon successfully validating the user, the API will return a JSON Web Token (JWT) token that must be used within 30 seconds.
  4. Use the JWT token to redirect the user to the URL: https://www.bissafety.app/sso/redirect/?token={JWT_TOKEN}

 Note: If you are using the system's CUSTOM URL feature, then please replace www.bissafety.app with your custom domain.

Endpoint
POST /user/token
curl -X POST "https://www.bissafety.app/rest/v.01/user/token" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode 'user={"userid": "123456", "givenName": "Test", "surname": "User", "emailAddress": "test.user@example.com"}'
Request parameters
user json Form field required

This parameter is an array of user objects in JSON format. A maximum number of 200 users can be imported at a time.

Sample data
{
  "userid": "String - Required - Unique userid in third party system",
  "givenName": "String - Required",
  "middlename": "String - Optional",
  "surname": "String - Required",
  "location": "String - OPTIONAL - If location is not provided then new users will be added under default location",
  "parentlocation": "String - OPTIONAL - if location provided does not exists and new location is being created, the new location will be created under provided parent location",
  "role": "String - OPTIONAL",
  "emailAddress": "String - Recommended",
  "address": "String - Optional",
  "city": "String - Optional",
  "country": "String - Optional",
  "province": "String - Optional",
  "postalcode": "String - Optional",
  "manager": "String - Optional - Unique userid in third party system",
  "managerEmail": "String - manager's email",
  "language": "String - Optional - Default English",
  "startDate": "Date - Optional - YYYY-MM-DD Date format",
  "SubCompanyName": "String - Optional - Only needed when a company has sub companies and want user to login to sub company",
  "CourseCode": "String - Optional - Course to auto-add and launch on login. Accepts either your registered course code (see Create Course Code) OR the encrypted 'courseid' returned by GET /training/contentpoolcourses. Launch requires the user's company to have the course via its course pool or eCommerce catalog."
}
SFTP Import
Automated Bulk User Upload

In addition to the on-demand functions listed above, automated bulk updates can be set up to run at scheduled intervals to perform the following functions:

  • Create user accounts
  • Update user information
  • Deactivate user accounts

To accomplish this, an automated process is set up to transfer data files containing account modification requests via a Secure File Transfer Protocol (SFTP). SFTP is a method of sending and receiving encrypted files to provide higher levels of security.

Please fill out our SFTP User Data Import Form to set up this automated method of file transfer for your company.

File Type

We recommend Excel files. Comma Separated Value (CSV) spreadsheet files, plain text (TXT) files, and Excel files are commonly used for bulk updates. Download a sample excel file here.

Update Type

We highly recommend that user information is updated using the delta file instead of doing a complete update each time. The delta file contains only new user information or changed user information and allows for a "Modification" method. This method avoids concerns about losing user data during automated updates when clients manually add users.

Frequency

We recommend scheduling a nightly update for a specific time. More frequent updates can be scheduled, but we do not recommend more than four in any given day.

Dataset

The dataset for bulk automated user uploads follow the same protocols as those for the User API endpoint. Refer to the Users section above for details regarding locations, company roles, system user roles, sub companies, and custom fields. 

The dataset includes, but is not limited to, the following fields:

  • User ID (required*)
  • Last Name (required*)
  • First Name (required*)
  • Middle Name (optional)
  • Address (optional)
  • City (optional)
  • Province (required*)
  • Country (required*)
  • Postal Code (optional)
  • SIN/SSN (not recommended)
  • Birthdate (not recommended)
  • Language (required*)
  • Work Phone (optional)
  • Cellphone (recommended)
  • Home Phone (optional)
  • Location ID Code (optional)
  • Location Name (optional)
  • Parent Location ID Code (optional)
  • Adding/Removing System User Role (optional)
  • Adding/Removing Company Role (optional)
  • Email (optional)
  • Evaluator (optional)
  • Start Date (optional)
  • Termination Date (optional)
  • Employee Status (A-Active/I-Deactivated) (required*)
  • Company (optional)
  • Other custom fields
User ID

It’s very important that user accounts use the company’s internal employee ID when the User ID dataset is required. The User ID must be a unique identifier to help link the accounts. Using internal employee IDs allows data to flow more effectively across systems and causes fewer issues when connecting to other systems in the future.

NOTE: In situations where an employee account is needed in the system before an internal employee ID is available, an employee account can be created without a User ID. Our system can search for orphan accounts that don’t have User IDs, cross verify the last name, first three letters of the first name, and one piece of account information (e.g. address, phone, email, etc.). If there is a match, the system adds the User ID to the existing orphaned user account, preventing duplicate or unlinked accounts.

Location ID Code

The location ID code is a unique identifier that can be entered into each location under the Users tab. This allows companies to have a user-friendly name (e.g. Leduc Office) and a unique ID code from the system for each location. When setting up the Users tab, it’s important to enter these codes into each location so that the system can properly import users into the correct locations. During the automated bulk update process, if a location in the imported data doesn’t exist in the system, the new location will be added and shown on the update log, which is received automatically after each import.

Custom Roles

If you are using the Training Matrix, it’s efficient to include the user’s company role during a user import so that the system can automatically map out all the user’s training requirements.

BambooHR Integration

We support Single Sign-On (SSO) integration and automatic user provisioning through the BambooHR platform.

Our system functions as a Service Provider (SP) and uses BambooHR to authenticate and authorize user access via OpenID Connect. OpenID Connect operates on protocols within the OAuth 2.0 framework to verify user identity, enabling seamless SSO capabilities. Once SSO is configured, users can bypass the BIS Safety Software login screen and access their homepage directly after logging into BambooHR.

For more information on OpenID, please refer to their tutorial How OpenID Connect Works - OpenID Foundation. 

Open API

Calls to these endpoints require a set of different API Credentials, which can be provided by your BIS Account Manager. A sample API call shows how to use client_id and client_secret as request header to call this API end point.

Training Verification

This API can be used to verify a training that is completed in BIS Safety Software by using the ID (Completion ID) and last name of the user.

The status of training verification can have one of the following values:

  • valid

  • invalid - did not find the matching training

  • expired - training expired

  • unverified - if the training was virtually proctored, then 'unverified' means the training was not verified

Endpoint
GET /training/verification
curl -X GET "https://www.bissafety.app/rest/v.01/training/verification?id=ID&lastname=LASTNAME" \
-H "client_id: CLIENT_ID" \
-H "client_secret: CLIENT_SECRET"
Request parameters
id string Query required

The ID of the certificate that needed to be verified.

lastname string Query required

Last name of the user who completed the training.

Sample response
{
  "status": "valid",
  "coursename": "COURSE_NAME",
  "expirydate": "YYYY-MM-DD",
  "completiondate": "YYYY-MM-DD"
}
Network Partners

This API can be used to fetch public network partners from BIS Safety Software.

 

Endpoint
GET /training/networkpartners
curl -X GET "https://www.bissafety.app/rest/v.01/training/networkpartners" \
-H "client_id: CLIENT_ID" \
-H "client_secret: CLIENT_SECRET"
Sample response
{
  "status": "success",
  "networkparteners": [
    "Network Partner 1",
    "Network Partner 2",
    "Network Partner 3",
    "Network Partner 4",
    "Network Partner 5"
  ]
}
Rewards

Rewards APIs allow an external system to read a user's current reward point balance and set it to a new total. The Rewards module must be enabled for the company, and each endpoint must be granted to the API credential before it can be called.

Get Reward Points

Returns each user's first name, last name, location, username, User ID, email and current reward point total. Filter by userid, bisinternaluserid, username or email, or call it with no filter to page through all users. When more records remain past the returned page, the response status is 202 instead of 200.

Endpoint
GET /reward/points
curl -X GET "https://www.bissafety.app/rest/v.01/reward/points?userid=USER_ID" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN"
Request parameters
userid string Query

The User ID is a unique and consistent identifier for each user in your system. Accepts a comma separated list to return several users at once.

bisinternaluserid numeric Query

System ID of a user in BIS.

username string Query

The username of the user's BIS account.

email string Query

The email address in the profile account of the user.

status string Query

A filter to get users with a certain status. By default, the API returns active users only "A". Use "I" to get inactive users.

Accepted values: A / I

includesubcompany numeric Query

This parameter is used for the companies that have sub companies. You can include users for all sub companies by specifying "1". By default, sub companies are not included "0". A sub company that does not have the Rewards module enabled is skipped.

Accepted values: 0 / 1

offset numeric Query

Offset the results by a certain value. By default, the offset is zero "0".

recordsperpage numeric Query

Limit the number of users that are returned up to a maximum of 500. A larger value is trimmed to 500.

Sample response
{
  "count": 1,
  "offset": 0,
  "recordsperpage": 500,
  "users": [
    {
      "userid": "EMP1042",
      "bisinternaluserid": 123456,
      "firstname": "Alice",
      "lastname": "Smith",
      "username": "alice.smith",
      "email": "alice.smith@example.com",
      "location": "Calgary",
      "points": 300
    }
  ]
}
Update Reward Points

Sets a user's reward point total to the value passed. The value is the new total, not a delta: if the user has 300 points and 50 is passed, the new total is 50. The difference is recorded as one adjustment in the user's point history. Supply exactly one of userid, bisinternaluserid, username or email; the identifier must match exactly one user, and both active and inactive users are matched. The request body must be form encoded (application/x-www-form-urlencoded); a JSON body is not supported. If another update for the same user is already in progress, the response status is 409.

Endpoint
POST /reward/points
curl -X POST "https://www.bissafety.app/rest/v.01/reward/points" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "userid=USER_ID&points=50"
Request parameters
points numeric Form field required

The new point total for the user, a whole number of zero or more. The user's total is set to this value; it is not added to the current total.

userid string Form field

The User ID of the user in your system. Supply exactly one of userid, bisinternaluserid, username or email.

bisinternaluserid numeric Form field

System ID of a user in BIS. Supply exactly one of userid, bisinternaluserid, username or email.

username string Form field

The username of the user's BIS account. Supply exactly one of userid, bisinternaluserid, username or email.

email string Form field

The email address in the profile account of the user. Supply exactly one of userid, bisinternaluserid, username or email.

reason string Form field

Text stored with the point adjustment and shown in the user's point history and the notification email.

notify numeric Form field

Send the reward notification email to the user when the total changes by specifying "1". By default no email is sent "0".

Accepted values: 0 / 1

includesubcompany numeric Form field

Search sub companies for the user as well by specifying "1". By default, only your own company is searched "0". A sub company that does not have the Rewards module enabled is skipped.

Accepted values: 0 / 1

Sample response
{
  "userid": "EMP1042",
  "bisinternaluserid": 123456,
  "previouspoints": 300,
  "points": 50,
  "adjustment": -250
}