{"openapi":"3.1.0","info":{"title":"BIS Safety Software REST API","version":"v.01","description":"The BIS Safety Software REST API (v.01) lets customer systems read and update users, training records, topics, forms, datasets, locations, assets, classroom events, tasks and reward points. Get a bearer token from `POST /token` with an API credential (Admin > Setup > Integration > API Credentials)."},"servers":[{"url":"https://www.bissafety.app/rest/v.01"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Authentication","description":"Applications access BIS Safety Software's APIs by first making a call to our authentication endpoint to acquire a **bearer token**.\n\nCalls 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.\n\n1. **Client ID**: A unique secret company identification number\n2. **Client Secret**: A secret security key for BIS Safety Software authentication\n\nThe 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.\n\nYour 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."},{"name":"Users","description":"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.\n\n**Location**\n\nAPI 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.\n\nOur 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.\n\nNew locations can be created when APIs are executed using the AddLocation request parameter.\n\n**Request Parameters**\n\nAddLocation *numeric*\n\nAllows 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.\n\nAccepted values: **1** / **0**\n\n**Company Role**\n\nUsers 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.\n\n**Request Parameters**\n\nAddRole *numeric*\n\nAllows 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.\n\nAccepted values: **1**/ **0**\n\n**Primary Role**\n\nUsers 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.\n\n**Request Parameters**\n\nAddRole *numeric*\n\nAllows 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.\n\nAccepted values: **1**/ **0**\n\n**System User Role**\n\nUsers 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.)\n\n**Subcompany Name**\n\nWhen 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.\n\nData from sub portals can be included when data is retrieved using API endpoints are executed using request parameters.\n\n**Custom Fields**\n\nYour 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.\n\nYou 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_”.\n\nIn 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’}.\n\n![](https://www.bissafety.app/v1/assets/img/API_Custom_Field.png)"},{"name":"Training","description":"You can get training records for users using two API endpoints described below."},{"name":"Forms","description":"There are two API endpoints that can be used to get form data and completed forms."},{"name":"Dataset","description":"Dataset APIs allow searching datasets, retrieving dataset records, and adding or updating dataset records by encrypted dataset and column identifiers."},{"name":"Location","description":"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."},{"name":"Training Topic","description":"Training topics are the requirements that user gets assigned by training matrix."},{"name":"Roles","description":"This API endpoint gets company roles."},{"name":"Task","description":"Users can be assigned tasks from the task module and from within Task Assignment field in digital forms."},{"name":"E-Commerce","description":"API endpoints related to company's E-commerce store."},{"name":"Asset","description":"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."},{"name":"Classroom Event","description":"There are three API endpoints to get and update classroom events."},{"name":"Single Sign-On (SSO)","description":"**SSO** is a user/session authentication service that allows a user to use one set of login credentials to access multiple applications.\n\nBIS 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.\n\n###### SSO Functionality\n\nThere are several features built into the SSO service:\n\n* **Creation of a new account**: New accounts are created for any new users as soon as they click the SSO link.\n* **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.\n* **Adding courses**: The SSO service can automatically add courses to existing or new accounts by providing \"Course ID\" with SSO requests.\n* **Automatic user provisioning**: User accounts are automatically added, updated, and deactivated based on changes in your Azure active directory."},{"name":"Open API","description":"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."},{"name":"Rewards","description":"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."}],"paths":{"/token":{"post":{"tags":["Authentication"],"summary":"Authentication","description":"Applications access BIS Safety Software's APIs by first making a call to our authentication endpoint to acquire a **bearer token**.\n\nCalls 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.\n\n1. **Client ID**: A unique secret company identification number\n2. **Client Secret**: A secret security key for BIS Safety Software authentication\n\nThe 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.\n\nYour 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.","operationId":"auth","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"grant_type":{"type":"string","default":"client_credentials","description":"The only supported value is 'client_credentials'."},"client_id":{"type":"string","description":"The secret unique Client ID given by BIS Account Managers."},"client_secret":{"type":"string","description":"The secret BIS Safety Software Key provided by BIS Account Managers."}},"required":["grant_type","client_id","client_secret"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "scope": "",
  "access_token": "YOUR_TOKEN",
  "expires_in": 3600,
  "token_type": "bearer"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[]}},"/user":{"get":{"tags":["Users"],"summary":"List Users","description":"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.\n\nEach role's **primary** field is returned only when the primary role feature is turned on for your company.","operationId":"user-list","parameters":[{"name":"userid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS.","schema":{"type":"number"}},{"name":"location","in":"query","required":false,"description":"The location name or location ID code of a specific location in your\ncompany hierarchy. The company hierarchy is the company structure\nshown in the Users tab, which structures your company's employees,\ncontractors, clients, customers, etc. by location, sub locations,\ndepartments, or however best meets your company's needs.","schema":{"type":"string"}},{"name":"role","in":"query","required":false,"description":"The user's specific company role or job title indicated by the role name or code.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"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 \"\".\n\n**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.\n\nAccepted values: **A** / **I** / \"\"","schema":{"type":"string","default":"A"}},{"name":"firstname","in":"query","required":false,"description":"Filters users by first name.","schema":{"type":"string"}},{"name":"lastname","in":"query","required":false,"description":"Filters users by last name.","schema":{"type":"string"}},{"name":"birthdate","in":"query","required":false,"description":"Filters users by their birthdate specified in the date format (YYYY-MM-DD).","schema":{"type":"string","format":"date"}},{"name":"modified","in":"query","required":false,"description":"Filter users that were added or modified after a certain date time specified in ISO date format (YYYY-MM-DDTHH:MM:SSZ).","schema":{"type":"string","format":"date"}},{"name":"includesubcompany","in":"query","required":false,"description":"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\".\n\nAccepted values: **0** / **1**","schema":{"type":"number","default":0}},{"name":"offset","in":"query","required":false,"description":"Offset the results by a certain value. By default, the offset is zero \"0\".","schema":{"type":"number","default":0}},{"name":"recordsperpage","in":"query","required":false,"description":"Limit the number of users that are returned up to a maximum of 1000.","schema":{"type":"number","default":500}},{"name":"includeqrcode","in":"query","required":false,"description":"When value is 1, user QR code data is included in response.","schema":{"type":"number","default":0}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
      }
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Users"],"summary":"Import Users","description":"You can**add** , **update** , and **deactivate** users using this API endpoint.  \nReturns 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.\n\nUsers 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.\n\nWhen 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.\n\nAn **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.","operationId":"user-import","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"users":{"type":"string","description":"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.","examples":["[\r\n  {\r\n    \"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).\",\r\n    \"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.\",\r\n    \"firstname\": \"String - Required\",\r\n    \"preferredname\": \"String - Optional\",\r\n    \"middlename\": \"String - Optional\",\r\n    \"lastname\": \"String - Required\",\r\n    \"location\": \"String - OPTIONAL - If location or locationcode is not provided then new users will be added under default location\",\r\n    \"locationcode\": \"String - OPTIONAL\",\r\n    \"parentlocation\": \"String - OPTIONAL\",\r\n    \"parentlocationcode\": \"String - OPTIONAL\",\r\n    \"companyrole\": \"String - OPTIONAL\",\r\n    \"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\",\r\n    \"email1\": \"String - Recommended\",\r\n    \"email2\": \"String - Optional\",\r\n    \"address\": \"String - Optional\",\r\n    \"city\": \"String - Optional\",\r\n    \"country\": \"String - Optional - Default Portal's country\",\r\n    \"stateprov\": \"String - Optional - Default Portal's state/province\",\r\n    \"postalcode\": \"String - Optional\",\r\n    \"workphone\": \"String - Optional\",\r\n    \"cellphone\": \"String - Optional\",\r\n    \"homephone\": \"String - Optional\",\r\n    \"evaluator\": \"String - Optional - User's manager userid\",\r\n    \"evaluator2\": \"String - Optional - User's Evaluator 2 field userid\",\r\n    \"birthdate\": \"Date - Optional - Date YYYY-MM-DD format\",\r\n    \"startdate\": \"Date - Optional - Date YYYY-MM-DD format\",\r\n    \"terminationdate\": \"Date - Optional - Date YYYY-MM-DD format\",\r\n    \"employer\": \"String - Optional\",\r\n    \"status\": \"String Required - Accepted value A and I\",\r\n    \"language\": \"String - Optional - Accepted value English/French/German/Español - Default English\",\r\n    \"emergencyContactName\": \"String - Optional - Emergency contact name\",\r\n    \"emergencyContactMobile\": \"String - Optional - Emergency contact phone\",\r\n    \"customfields\": \"Struct - Optional - this is structure of all custom fields with values - Default {}\",\r\n    \"addlocation\": \"Numeric - Optional - What should be done if location provide does not exists - Accepted value 0/1 - Default 1\",\r\n    \"updatelocation\": \"Numeric - Optional - update location - Accepted value 0/1 - Default 0\",\r\n    \"addParentLocation\": \"Numeric - Optional - add parent location if does not eixsts - Accepted value 0/1 - Default 0\",\r\n    \"useDefaultLocation\": \"Numeric - Optional - What should be done if location provide does not exists and addlocation is 0 - Accepted value 0/1 - Default 1\",\r\n    \"addrole\": \"Numeric - Optional - What should be done if company role provide does not exists - Accepted value 0/1 - Default 1\",\r\n    \"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.\",\r\n    \"addsystemroles\": \"String - Optional - list of system roles that need to be added to user\",\r\n    \"removesystemroles\": \"String - Optional - list of system roles that need to be removed from user\",\r\n    \"subcompanyname\": \"Optional - Only needed when a company has sub companies and want to update users under sub company\",\r\n    \"socialinsurancenumber\": \"String - Optional\",\r\n    \"bisinternaluserid\": \"Optional - Unique ID in BIS\",\r\n    \"onlyUpdateAPICompanyRole\": \"Optional - If 1 then do not remove roles added by admins, only remove roles added by API - Accepted value 0/1 - Default 0\",\r\n    \"profilePicture\": \"Optional - You can pass Base64 String to update the profile picture for the user. File size is limited to 2MB.\",\r\n    \"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.\",\r\n    \"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.\",\r\n    \"sendInvitationEmailOnCreation\": \"Numeric - Optional - Pass 1 if you want the users to receive account invitation email upon account creation - Accepted value 0/1 - Default 0.\",\r\n    \"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.\",\r\n    \"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.\"\r\n  }\r\n]"]},"returnlogs":{"type":"number","default":0,"description":"Returns additional logs of each user field updated.\n\nAccepted values: **1** /**0**"}},"required":["users"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":[
  {
    "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
  }
]}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/user/documents":{"get":{"tags":["Users"],"summary":"Get Documents","description":"You can use this API endpoint to get the documents that are uploaded in a user's profile in BIS Safety Software.","operationId":"user-documents","parameters":[{"name":"userid","in":"query","required":true,"description":"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.","schema":{"type":"string","default":"-1"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/user/login":{"post":{"tags":["Users"],"summary":"Login","description":"This API can be used to validate user's username and password and return some basic details of the user.","operationId":"user-login","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"type":"string","description":"Username used by user to login to BIS."},"password":{"type":"string","description":"Password used by user to login to BIS."}},"required":["username","password"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "status": "success",
  "user": {
    "lastname": "LASTNAME",
    "firstname": "FIRSTNAME",
    "bisinternaluserid": "BIS_INTERNAL_USERID",
    "email": "EMAIL"
  }
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/user/siteactivity":{"post":{"tags":["Users"],"summary":"Site Activity","description":"You can use this API endpoint to get last date and time the user accessed this site.\n\nThe response from this API will be the exact same **records** parameter, but with two additional fields **status** and **message.**","operationId":"site-activity","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"records":{"type":"string","description":"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.","examples":["[\r\n    {\r\n        \"userid\": \"String - Required - Unique userid in third party system\",\r\n\t\"siteid\": \"String - Required - Unique siteid in third party sysytem\",\r\n\t\"activityDate\": \"Date in ISO format - Required - The last date and time the user accessed the site.\"\r\n    }\r\n]"]}},"required":["records"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
    "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"
        }
    ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/training":{"get":{"tags":["Training"],"summary":"Completed Training","description":"You can get users' completed training. The results will include all online courses, forms, and historical completed training records.\n\nNote: 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.","operationId":"training-trainings","parameters":[{"name":"userid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS.","schema":{"type":"number"}},{"name":"coursecode","in":"query","required":false,"description":"External course id of the course to get completions for a specific course.","schema":{"type":"string"}},{"name":"email","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"lastname","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"fromdate","in":"query","required":false,"description":"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.\n\nNOTE: Total number of days between the fromdate and todate must be 30 days or less.","schema":{"type":"string","format":"date"}},{"name":"todate","in":"query","required":false,"description":"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.\n\nNOTE: Total number of days between the fromdate and todate must be 30 days or less.","schema":{"type":"string","format":"date"}},{"name":"onlypassed","in":"query","required":false,"description":"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.\n\nAccepted values: **1** /**0**","schema":{"type":"number","default":1}},{"name":"status","in":"query","required":false,"description":"Leave blank to retrieve results for all course types.\n\nAccepted values: **Public** /**Private**","schema":{"type":"string"}},{"name":"type","in":"query","required":false,"description":"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.\n\nAccepted values: **TR** / **AF** / **OC**","schema":{"type":"string"}},{"name":"deletedrecord","in":"query","required":false,"description":"This parameter is used to get deleted **Training Records** only. By default, this parameter is set to 0\n\nAccepted values: **0** / **1**","schema":{"type":"number","default":0}},{"name":"includesubcompany","in":"query","required":false,"description":"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\".\n\nAccepted values: **0** / **1**","schema":{"type":"number","default":0}},{"name":"includeincompletecourses","in":"query","required":false,"description":"This parameter is used to get incomplete course completions. By default this parameter is set to 0.\n\nAccepted values: **0** / **1**","schema":{"type":"number"}},{"name":"datefilter","in":"query","required":false,"description":"`completion` (default): `fromdate`/`todate` filter on the completion date - the historical behavior.\n\n`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.","schema":{"type":"string","default":"completion"},"example":"modified"}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Training"],"summary":"Push Training Records","description":"This API endpoint imports training record.\n\nThe response from this API will be the exact same **records** parameter, but with two additional fields **status** and **message**","operationId":"pushrecord","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"records":{"type":"string","description":"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.\n\nWhen **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.","examples":["[\r\n  {\r\n    \"userid\": \"String - Required - Unique userid in third party system\",\r\n    \"courseid\": \"String - Required - Unique customer course id\",\r\n    \"completiondate\": \"Date - Required - Date YYYY-MM-DD format\",\r\n    \"score\": \"Number - Optional - Accepted value 0 to 100 - Default 100\",\r\n    \"trainingprovider\": \"String - OPTIONAL - Training provider for the course\",\r\n    \"expirydate\": \"Date - Optional - Date YYYY-MM-DD format - Only applicable if 'Expiry Override' is enabled for the course\",\r\n    \"archiveOldRecords\" : \"Number - Optional - Accepted value 1 - Default ''\"\r\n  }\r\n]"]},"includesubcompany":{"type":"number","description":"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\".\n\nAccepted values: **0** / **1**"}},"required":["records"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/training/online":{"get":{"tags":["Training"],"summary":"Online Course Result","description":"This API endpoint returns all completed, in progress, and not started online courses with their results and progress details.","operationId":"training-online","parameters":[{"name":"userid","in":"query","required":true,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS. Note: If this parameter is passed then userid parameter is not required.","schema":{"type":"number"}},{"name":"courseid","in":"query","required":false,"description":"The course ID set up for the online course and specific to each company.","schema":{"type":"string"}},{"name":"includesubcompany","in":"query","required":false,"description":"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\".\n\nAccepted values: **0** / **1**","schema":{"type":"number"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/training/contentpoolcourses":{"get":{"tags":["Training"],"summary":"Courses in Course Pool","description":"This API endpoint gets a list of all courses in your course pool.","operationId":"contentpool-courses","parameters":[{"name":"modified","in":"query","required":false,"description":"All online courses that were modified after the date(yyyy-mm-dd format) will be returned.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/training/createcoursecode":{"post":{"tags":["Training"],"summary":"Create Course Code","description":"This API endpoint creates a course code for the passed course ID and responds with the course code.","operationId":"create-course-code","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"courseid":{"type":"string","description":"The Course ID you get from /contentpoolcourses needs to be passed here."},"quantity":{"type":"number","description":"Number of seats to be added to the course code."},"location":{"type":"string","description":"The location name where users will be added to when they register using the course code."},"expirydate":{"type":"string","format":"date","description":"Expiry date for the course code in YYYY-MM-DD date format."},"notes":{"type":"string","description":"Notes about the code created."},"upgrade":{"type":"number","default":0,"description":"Add Virtual Proctoring to the course code. By default, the upgrade is zero \"0\".\n\nAccepted values: **0** / **1**"}},"required":["courseid","quantity","location","expirydate","notes"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "status": "success",
  "coursecode": "COURSECODE"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/training/courses":{"get":{"tags":["Training"],"summary":"Training Courses","description":"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.\n\nThe **priceDetails** , **courselink** , **policy** , **requirements** and **duration** fields are returned only when you filter with `coursetype=classroom`.","operationId":"training-courses","parameters":[{"name":"includesubcompany","in":"query","required":false,"description":"This parameter is used for the companies that have sub companies. You\ncan include users for all sub companies. By default, sub companies are\nnot included \"0\".\n\nAccepted values: **0** / **1**","schema":{"type":"number"}},{"name":"coursetype","in":"query","required":false,"description":"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`.","schema":{"type":"string","default":"all"}},{"name":"modified","in":"query","required":false,"description":"All courses that was modified after the date(yyyy-mm-dd format) will be returned.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
        }
      ]
    }
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/form/response":{"get":{"tags":["Forms"],"summary":"Get Form Data","description":"This API endpoint returns data entered by users into specific fields for a particular form. The data also includes form completion records.","operationId":"forms-response","parameters":[{"name":"formid","in":"query","required":true,"description":"Data is fetched from the form with this form ID.","schema":{"type":"string","default":"-1"}},{"name":"fields","in":"query","required":false,"description":"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.).","schema":{"type":"string","default":"0"}},{"name":"filter","in":"query","required":false,"description":"A JSON object structure (field and and value combination) to filter results for certain user entries (e.g. {\"DD_11\":\"VALUE1\", \"CH_12\":\"VALUE2\"}).","schema":{"type":"string","default":"0"}},{"name":"includeinprogress","in":"query","required":false,"description":"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.\n\nAccepted values: **0** / **1**","schema":{"type":"number","default":0}},{"name":"fromdate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date","default":"0"}},{"name":"todate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date","default":"0"}},{"name":"offset","in":"query","required":false,"description":"Offset the results by a certain value. By default, the offset is zero \"0\".","schema":{"type":"number","default":1}},{"name":"recordsPerPage","in":"query","required":false,"description":"Limit the form data returned by the number of different users entering data up to a maximum of 1000.","schema":{"type":"number","default":100}},{"name":"modified","in":"query","required":false,"description":"Filters form completions that were completed or updated after a certain date time in ISO date format (YYYY-MM-DDTHH:MM:SSZ).","schema":{"type":"string","format":"date","default":"0"}},{"name":"completionid","in":"query","required":false,"description":"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.","schema":{"type":"string","default":"0"},"example":"H_99999999 / E_99999999"}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/form/completions":{"get":{"tags":["Forms"],"summary":"Get Completions","description":"This API endpoint gets completion records for forms.","operationId":"forms-completions","parameters":[{"name":"formid","in":"query","required":false,"description":"The completion records are fetched for the form with this form ID.\n\nNOTE: Required if fromdate and todate parameters are not provided.","schema":{"type":"string","default":"-1"}},{"name":"filter","in":"query","required":false,"description":"A JSON object structure (field and and value combination) to filter results for certain user entries (e.g. {\"DD_11\":\"VALUE1\", \"CH_12\":\"VALUE2\"}).","schema":{"type":"string","default":"0"}},{"name":"fromdate","in":"query","required":false,"description":"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.\n\nNOTE: Required if the Form ID is not provided.","schema":{"type":"string","format":"date","default":"0"}},{"name":"todate","in":"query","required":false,"description":"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.\n\nNOTE: Required if the Form ID is not provided.","schema":{"type":"string","format":"date","default":"0"}},{"name":"offset","in":"query","required":false,"description":"Offset the results by a certain value. By default, the offset is zero \"0\".","schema":{"type":"number","default":1}},{"name":"recordsPerPage","in":"query","required":false,"description":"Limit the number of form completion records up to a maximum of 1000.","schema":{"type":"number","default":100}},{"name":"includeformpdf","in":"query","required":false,"description":"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.\n\nAccepted values: **0** /**1**","schema":{"type":"number","default":0}},{"name":"completionid","in":"query","required":false,"description":"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.","schema":{"type":"string"},"example":"H_99999999 / E_99999999"},{"name":"eventhistoryid","in":"query","required":false,"description":"Pass the value of the Event ID you want to fetch form completions for.","schema":{"type":"number","default":0}},{"name":"modifieddate","in":"query","required":false,"description":"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.\n\nMatching 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).\n\nThis parameter can be supplied on its own — when it is present, the requirement to supply either formid or (fromdate and todate) is waived.","schema":{"type":"string","format":"date","default":"0"},"example":"2026-07-23"},{"name":"assetid","in":"query","required":false,"description":"Returns only completions linked to this asset. Use the asset ID returned by the `GET /asset` endpoint.\n\nFor 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.\n\nIf both `assetid` and `serialnumber` are supplied, `assetid` is used and `serialnumber` is ignored.\n\nAn 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\").\n\nThis parameter can be supplied on its own — when it is present, the requirement to supply formid, modifieddate or (fromdate and todate) is waived.","schema":{"type":"string"}},{"name":"serialnumber","in":"query","required":false,"description":"Alternative to `assetid`. Returns only completions linked to the active company asset with this exact serial number, and filters the same way `assetid` does.\n\nIgnored when `assetid` is also supplied.\n\nIf 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.\n\nThis 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.","schema":{"type":"string"},"example":"SN-100234"},{"name":"bisinternaluserid","in":"query","required":false,"description":"Returns only completions belonging to this user. Use the value of the `BISInternalUserId` key returned in completion records.\n\nUnknown IDs are not rejected — they simply return no completions.\n\nThis parameter cannot be used on its own: one of formid, modifieddate, an asset filter or (fromdate and todate) is still required.","schema":{"type":"number","default":0},"example":123456}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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}"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/form":{"get":{"tags":["Forms"],"summary":"Get Form Fields","description":"This API endpoints returns form fields for a given form ID.","operationId":"form-fields","parameters":[{"name":"formid","in":"query","required":true,"description":"The completion records are fetched for the form with this form ID.","schema":{"type":"string","default":"-1"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
    "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
    }
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/form/completion-pdf":{"get":{"tags":["Forms"],"summary":"Get Form PDF Link","description":"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.","operationId":"completion-pdf","parameters":[{"name":"completionid","in":"query","required":true,"description":"Completion identifier is available in the /form/completions or /form/response API response.","schema":{"type":"string"},"example":"H_99999999 / E_99999999"},{"name":"layoutid","in":"query","required":false,"description":"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.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"linkExpiry":600,"status":1,"pdf":"{pdf link for the completion}"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/dataset":{"get":{"tags":["Dataset"],"summary":"List Datasets","description":"Returns active company datasets with encrypted dataset and column identifiers that support API access.","operationId":"list-datasets","parameters":[{"name":"searchText","in":"query","required":false,"description":"Optional search text to match dataset name or category name.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
        }
      ]
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/dataset/records":{"get":{"tags":["Dataset"],"summary":"Get Dataset Records","description":"Returns dataset rows using encrypted dataset column IDs as keys. Requires dataset API access.","operationId":"get-dataset-records","parameters":[{"name":"datasetId","in":"query","required":true,"description":"Encrypted dataset ID returned by the List Datasets endpoint.","schema":{"type":"string"}},{"name":"searchText","in":"query","required":false,"description":"Optional search text to filter records (if supported).","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "rows": [
    {
      "_5AFE7E5E459DEA7B5902F05694BF682F": "1",
      "_6F993159D2A77884F1F0AD837EA6AE61": "Alice",
      "_7080EAC82B0CF785971A446766E38B934": "Toronto"
    },
    {
      "_5AFE7E5E459DEA7B5902F05694BF682F": "2",
      "_6F993159D2A77884F1F0AD837EA6AE61": "Bob",
      "_7080EAC82B0CF785971A446766E38B934": "Vancouver"
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Dataset"],"summary":"Add Dataset Records","description":"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.\n\nPlease note that the **dataset must have a Unique column** in order to use this endpoint.\n\neg.\n\n![Unique Field Example](https://www.bissafety.app/assets/images/apidoc/add-edit-dataset-records-uniquefield.png)","operationId":"add-dataset-records","parameters":[{"name":"datasetId","in":"query","required":true,"description":"Dataset ID as returned by the List Datasets endpoint.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"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.","content":{"application/json":{"schema":{"type":"array"},"example":[
  {
    "_5AFE7E5E459DEA7B5902F05694BF682F": "1",
    "_6F993159D2A77884F1F0AD837EA6AE61": "Alice",
    "_7080EAC82B0CF785971A446766E38B934": "Toronto"
  }
]}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "success": 1,
  "summary": {
    "added": 2,
    "updated": 0,
    "skipped": 0
  },
  "results": [
    {
      "status": "added",
      "message": "Record added."
    },
    {
      "status": "added",
      "message": "Record added."
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"delete":{"tags":["Dataset"],"summary":"Delete Dataset Records","description":"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.","operationId":"delete-dataset-records","parameters":[{"name":"datasetId","in":"query","required":true,"description":"Encrypted dataset ID returned by the List Datasets endpoint.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"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.","content":{"application/json":{"schema":{"type":"object"},"example":{
  "uniqueValues": ["1", "2"]
}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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."
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/location":{"get":{"tags":["Location"],"summary":"List Locations","description":"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.","operationId":"location-list","parameters":[{"name":"includesubcompany","in":"query","required":false,"description":"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\".\n\nAccepted values: **0** / **1**","schema":{"type":"number"}},{"name":"status","in":"query","required":false,"description":"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 \"\".\n\nAccepted values: **A** / **I** / \"\"","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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": ""
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Location"],"summary":"Import Locations","description":"You can add, update locations using this API endpoint.","operationId":"location-import","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"locations":{"type":"string","description":"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.","examples":["{\r\n  \"locationname\": \"String - Required\",\r\n  \"locationcode\": \"String - Recommended\",\r\n  \"parentlocationname\": \"String - Optional\",\r\n  \"parentlocationcode\": \"String - Optional\",\r\n  \"postalcode\": \"String - Optional\",\r\n  \"billto\": \"String - Optional\",\r\n  \"stateprov\": \"String - Optional\",\r\n  \"email\": \"String - Optional\",\r\n  \"subcompanyname\": \"In-House BIS\",\r\n  \"city\": \"String - Optional\",\r\n  \"country\": \"String - Optional\",\r\n  \"maincontact\": \"String - Optional\",\r\n  \"address\": \"String - Optional\",\r\n  \"timezone\": \"String - Optional - Value should be in time offset of UTC for example MST is -07:00\",\r\n  \"website\": \"String - Optional\",\r\n  \"workphone\": \"String - Optional\",\r\n  \"status\": \"String Optional - Accepted value A and I\"\r\n}"]}},"required":["locations"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":[
  {
    "locationname": "Location 1",
    "message": "Updated.",
    "error": 0,
    "locationcode": "Unique Code"
  }
]}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/location/status":{"post":{"tags":["Location"],"summary":"Change Location Status","description":"You can use this API endpoint will activate or deactivate a location.","operationId":"location-status","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"locationname":{"type":"string","description":"Name of the location. Required if locationcode is not passed."},"locationcode":{"type":"string","description":"Code of the location. Required if locationname is not passed."},"action":{"type":"string","description":"Whether to activate or deactivate a location.\n\nAccepted values: **activate** / **deactivate**"}},"required":["action"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "status": "success",
  "message": "location was deactivated successfully"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/topic/details":{"get":{"tags":["Training Topic"],"summary":"Topic Details","description":"This API endpoint will return all training topics and courses mapped to them.","operationId":"topic-details","parameters":[{"name":"topicid","in":"query","required":false,"description":"Comma separated list of topic ids.","schema":{"type":"string"}},{"name":"bisinternaltopicid","in":"query","required":false,"description":"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`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
      }]
    }]
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/topic/assigned":{"get":{"tags":["Training Topic"],"summary":"Topic Assigned","description":"This API endpoint will return all users and their assigned topics.","operationId":"topic-assigned","parameters":[{"name":"userid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS.","schema":{"type":"number"}},{"name":"topicid","in":"query","required":false,"description":"The unique topic ID for the training topic.","schema":{"type":"string"}},{"name":"bisinternaltopicid","in":"query","required":false,"description":"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`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/topic/status":{"get":{"tags":["Training Topic"],"summary":"Topic Status","description":"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.\n\nTopics 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.\n\n`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.\n\nOnly 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.\n\n**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`.","operationId":"topic-status","parameters":[{"name":"userid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS.","schema":{"type":"number"}},{"name":"topicid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"offset","in":"query","required":false,"description":"Offset the results by a certain value. By default, the offset is zero \"0\".","schema":{"type":"number","default":0}},{"name":"recordsperpage","in":"query","required":false,"description":"Limit the number of user and topic combinations returned up to a maximum of 500.","schema":{"type":"number","default":500}},{"name":"includeuserwithoutuserid","in":"query","required":false,"description":"Controls whether to include users without UserID set in the system. By Default, 0 = exclude users without UserIDs (default), 1 = include all users","schema":{"type":"number","default":0}},{"name":"includeduedate","in":"query","required":false,"description":"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\".","schema":{"type":"number","default":0}},{"name":"bisinternaltopicid","in":"query","required":false,"description":"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`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/topic/reset":{"get":{"tags":["Training Topic"],"summary":"Topic Reset","description":"This API endpoint find all the completions that satisfies the topic for a user and archive those completions.","operationId":"topic-reset","parameters":[{"name":"userid","in":"query","required":true,"description":"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.","schema":{"type":"string"}},{"name":"topicid","in":"query","required":false,"description":"The topic ID your administrators type on the topic. Send either `topicid` or `bisinternaltopicid`.","schema":{"type":"string"}},{"name":"bisinternaltopicid","in":"query","required":false,"description":"The BIS topic number, the `bisinternaltopicid` returned by `/topic/list`. Send either `topicid` or `bisinternaltopicid`. When both are sent, `bisinternaltopicid` is used.","schema":{"type":"number"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "status": "success",
  "message": "Topic was reset successfully"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/topic/list":{"get":{"tags":["Training Topic"],"summary":"Topic List","description":"Returns every training topic in your company with its IDs, without the courses and levels that `/topic/details` returns.\n\n`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.\n\nTopics 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.","operationId":"topic-list","parameters":[{"name":"offset","in":"query","required":false,"description":"Skip this many topics before the page starts. By default, the offset is zero \"0\".","schema":{"type":"number","default":0}},{"name":"recordsperpage","in":"query","required":false,"description":"How many topics one page returns. The default is 500 and the maximum is 10000.","schema":{"type":"number","default":500}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/topic/status/delta":{"get":{"tags":["Training Topic"],"summary":"Topic Status Delta","description":"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.\n\nLeave `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.\n\n`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`.\n\n`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.\n\nPages 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.\n\nExpiry, 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.","operationId":"topic-status-delta","parameters":[{"name":"lastupdateddate","in":"query","required":false,"description":"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.","schema":{"type":"string"},"example":"2026-07-30T00:00:00Z"},{"name":"cursor","in":"query","required":false,"description":"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.","schema":{"type":"string"},"example":"38893_90095_1785456251"},{"name":"userid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS. Comma separated for more than one.","schema":{"type":"number"}},{"name":"topicid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaltopicid","in":"query","required":false,"description":"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.","schema":{"type":"number"}},{"name":"includeoptional","in":"query","required":false,"description":"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.\n\nAccepted values: **1** / 0","schema":{"type":"number","default":1}},{"name":"includeuserwithoutuserid","in":"query","required":false,"description":"Controls whether to include users without UserID set in the system. Ignored when the request filters by `bisinternaluserid`.\n\nAccepted values: **0** / 1","schema":{"type":"number","default":0}},{"name":"includecount","in":"query","required":false,"description":"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.\n\nAccepted values: **0** / 1","schema":{"type":"number","default":0}},{"name":"recordsperpage","in":"query","required":false,"description":"Limit the number of user and topic records that are returned up to a maximum of 10000.","schema":{"type":"number","default":500}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
        }
      ]
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/role":{"get":{"tags":["Roles"],"summary":"Roles","description":"This API endpoint gets company roles.","operationId":"role","parameters":[{"name":"includesubcompany","in":"query","required":false,"description":"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\".\n\nAccepted values: **0** / **1**","schema":{"type":"number"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "roles": [{
    "role": "Test a role",
    "rolecode": "0023",
    "company": "In-House BIS"
  }, {
    "role": "Company Sanctioned Driver",
    "rolecode": "",
    "company": "In-House BIS"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/task":{"get":{"tags":["Task"],"summary":"Get Tasks","description":"This endpoint can be used to fetch all tasks in the system.","operationId":"get-task","parameters":[{"name":"taskstatus","in":"query","required":false,"description":"Returns all tasks with specified task status. If no task status is provided, then all pending tasks are returned.\n\nAccepted values: **Pending** /**Overdue** /**Completed** /**All**","schema":{"type":"string","default":"pending"}},{"name":"location","in":"query","required":false,"description":"Returns all tasks that are associated with the provided location. If no location is provided, then all tasks are returned.","schema":{"type":"string"}},{"name":"includearchived","in":"query","required":false,"description":"If this is set to 1, then all tasks that were assigned by archived forms will also be included in the response.\n\nAccepted values: **0** /**1**","schema":{"type":"number","default":0}},{"name":"fromdate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date"}},{"name":"todate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date"}},{"name":"taskid","in":"query","required":false,"description":"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.\n\nAn ID that is not a positive whole number returns the error \"Invalid Task ID Provided\".","schema":{"type":"number"},"example":145247},{"name":"completionid","in":"query","required":false,"description":"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).\n\nWhen 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.\n\nAn ID in any other format returns the error \"Invalid Completion ID Provided\".","schema":{"type":"string"},"example":"H_99999999 / E_99999999"}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/products":{"get":{"tags":["E-Commerce"],"summary":"Get Available Products","description":"This API gets the courses and products in the company's e-commerce store.\n\n**launchcode** is not returned by default. Contact your account manager to have it included.","operationId":"ecommerce","parameters":[{"name":"types","in":"query","required":false,"description":"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\".\n\nAccepted values: **Online** / **All**","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/asset/categories":{"get":{"tags":["Asset"],"summary":"Get Asset Categories","description":"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.","operationId":"get-asset-categories","responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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": []
      }
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/asset":{"get":{"tags":["Asset"],"summary":"List Assets","description":"Returns paginated assets for the authenticated company with optional filters (asset/category/status/type/location/serial/search), active-state filtering, and sorting.","operationId":"list-assets","parameters":[{"name":"assetid","in":"query","required":false,"description":"Asset id. When provided, response is limited to that asset.","schema":{"type":"string"}},{"name":"serialnumber","in":"query","required":false,"description":"Exact serial number filter (active company assets only).","schema":{"type":"string"}},{"name":"categoryid","in":"query","required":false,"description":"Asset category id filter.","schema":{"type":"string"}},{"name":"statusid","in":"query","required":false,"description":"Status id filter. Empty/0 means no status filtering.","schema":{"type":"string"}},{"name":"typeid","in":"query","required":false,"description":"Type id filter. Empty/0 means no type filtering.","schema":{"type":"string"}},{"name":"locationid","in":"query","required":false,"description":"Location id filter. Empty/0 means no location filtering.","schema":{"type":"string"}},{"name":"search","in":"query","required":false,"description":"Case-insensitive text search across name, serial number, manufacturer, model, description, and current site.","schema":{"type":"string"}},{"name":"active","in":"query","required":false,"description":"Asset state filter: `A` (active, default) or `I` (inactive). Any value other than `I` is treated as active.","schema":{"type":"string","default":"A"},"example":"A"},{"name":"offset","in":"query","required":false,"description":"Pagination offset (0-based).","schema":{"type":"number","default":0},"example":0},{"name":"recordsperpage","in":"query","required":false,"description":"Page size. Values are clamped to 1..500 on the server. Default is 50.","schema":{"type":"number","default":50},"example":50},{"name":"orderby","in":"query","required":false,"description":"Sort column key: `name`, `location`, `serialNumber`, or `description`. Any other value defaults to `name`.","schema":{"type":"string"}},{"name":"sortdirection","in":"query","required":false,"description":"Sort direction: `ASC` or `DESC`. Any non-`DESC` value defaults to `ASC`.","schema":{"type":"string"},"example":"ASC"}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Asset"],"summary":"Save Asset","description":"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.\n\nWhen 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}`.","operationId":"save-asset","parameters":[{"name":"assetid","in":"query","required":false,"description":"Asset ID of the asset to update (from GET /asset endpoint). If present and valid, API updates that asset.","schema":{"type":"string"}},{"name":"serialnumber","in":"query","required":false,"description":"Serial number lookup for update flow. Must resolve to exactly one active asset in the company.","schema":{"type":"string"}},{"name":"categoryid","in":"query","required":false,"description":"Category id for create flow.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"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`.\n\n**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`:\n\n* `textfield` – a plain text string.\n* `datefield` – a date string; stored as `YYYY-MM-DD`. Values that are not valid dates are ignored.\n* `multiplechoice` – the encrypted `optionId` of the selected option, taken from that field's `options[].optionId` in `GET /asset/categories`.\n* `multiselect` – an array of the selected options' `optionText` values (a single text string is also accepted).\n\nCall `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.","content":{"application/json":{"schema":{"type":"object"},"example":{
  "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"]
  }
}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "assetId": "ASSET_ID"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/asset/requiredDocuments":{"get":{"tags":["Asset"],"summary":"Get Asset Required Documents","description":"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.","operationId":"get-asset-required-documents","parameters":[{"name":"assetid","in":"query","required":false,"description":"Asset ID of the asset whose required documents you want to retrieve. Either `assetid` or `serialnumber` is required.","schema":{"type":"string"}},{"name":"serialnumber","in":"query","required":false,"description":"Serial number of the asset whose required documents you want to retrieve. Either `assetid` or `serialnumber` is required.","schema":{"type":"string"}},{"name":"includearchived","in":"query","required":false,"description":"Archive toggle: `0` active-only (default), `1` include archived.","schema":{"type":"number"},"example":0},{"name":"includeexpireddocuments","in":"query","required":false,"description":"Expiry toggle: `0` exclude expired (default), `1` include expired.","schema":{"type":"number"},"example":0}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/asset/requiredDocument":{"post":{"tags":["Asset"],"summary":"Add Asset Required Document","description":"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.","operationId":"add-asset-required-document","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"assetid":{"type":"string","description":"Asset ID of the asset to which the required document will be uploaded. Either `assetid` or `serialnumber` is required."},"serialnumber":{"type":"string","description":"Serial number of the asset to which the required document will be uploaded. Either `assetid` or `serialnumber` is required."},"documenttypeid":{"type":"string","description":"Required-document type id. Mandatory for upload."},"documentname":{"type":"string","description":"Optional display name for uploaded required document.","examples":["Operator License"]},"expirydate":{"type":"string","description":"Optional expiry date. If provided, use `YYYY-MM-DD`.","examples":["2026-12-31"]},"file":{"type":"string","format":"binary","description":"Required upload file. Allowed types: jpeg, jpg, png, pdf, xlsx, xls, docx, doc."}},"required":["documenttypeid","file"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "documentId": "REQUIRED_DOCUMENT_ID",
  "message": "Required document Operator License added"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"delete":{"tags":["Asset"],"summary":"Delete Required Document","description":"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.","operationId":"delete-required-document","parameters":[{"name":"requiredDocumentId","in":"query","required":true,"description":"Required-document id to archive. Sent in the query string.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "success": true,
  "message": "Document Operator License archived."
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/asset/documents":{"get":{"tags":["Asset"],"summary":"Get Asset Documents","description":"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.","operationId":"get-asset-documents","parameters":[{"name":"assetid","in":"query","required":false,"description":"Asset ID of the asset whose documents you want to retrieve. Either `assetid` or `serialnumber` is required.","schema":{"type":"string"}},{"name":"serialnumber","in":"query","required":false,"description":"Serial number of the asset whose documents you want to retrieve. Either `assetid` or `serialnumber` is required.","schema":{"type":"string"}},{"name":"includearchived","in":"query","required":false,"description":"Archive toggle: `0` active-only (default), `1` include archived.","schema":{"type":"number","default":0},"example":0},{"name":"search","in":"query","required":false,"description":"Free-text match against document name and uploader full name.","schema":{"type":"string"}},{"name":"sortcolumn","in":"query","required":false,"description":"Sort key: `docname` or `addeddate`. Any other value defaults to `docname`.","schema":{"type":"string","default":"docname"},"example":"docname"},{"name":"sortdirection","in":"query","required":false,"description":"Sort direction: `ASC` or `DESC`. Empty defaults to `ASC`; any non-`ASC` value is treated as `DESC`.","schema":{"type":"string","default":"ASC"},"example":"ASC"}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Asset"],"summary":"Add Asset Document","description":"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.","operationId":"add-asset-document","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"assetid":{"type":"string","description":"Asset ID of the asset to which the document will be uploaded. Either `assetid` or `serialnumber` is required."},"serialnumber":{"type":"string","description":"Serial number of the asset to which the document will be uploaded. Either `assetid` or `serialnumber` is required."},"documentname":{"type":"string","description":"Display name for saved document. Server appends uploaded extension and auto-deduplicates active names if needed.","examples":["Test Document"]},"expirydate":{"type":"string","description":"Optional expiry date. If provided, use `YYYY-MM-DD`.","examples":["2026-12-31"]},"file":{"type":"string","format":"binary","description":"Required upload file. Allowed types: jpeg, jpg, png, pdf, xlsx, xls, docx, doc."}},"required":["documentname","file"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "added": 1,
  "message": "Document added: Test Document.pdf"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"delete":{"tags":["Asset"],"summary":"Delete Asset Document","description":"Soft-archives an asset document by `documentid` and returns `success=true`. This endpoint uses HTTP DELETE and expects `documentid` in the query string.","operationId":"delete-asset-document","parameters":[{"name":"documentid","in":"query","required":true,"description":"Document id to archive (soft delete). Sent in the query string.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "success": true
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/asset/documents/update":{"post":{"tags":["Asset"],"summary":"Update Asset Document","description":"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.","operationId":"update-asset-document","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"documentid":{"type":"string","description":"Document id to modify."},"documentname":{"type":"string","description":"Optional new document title.","examples":["Updated Title"]},"expirydate":{"type":"string","description":"Optional new expiry date in `YYYY-MM-DD` format.","examples":["2027-01-15"]}},"required":["documentid"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "success": true
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/event":{"get":{"tags":["Classroom Event"],"summary":"List Events","description":"This API endpoint gets all classroom calendar events.","operationId":"list-events","parameters":[{"name":"fromdate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date"}},{"name":"todate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date"}},{"name":"status","in":"query","required":false,"description":"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.\n\nAccepted values: **A** / \"\"","schema":{"type":"string"}},{"name":"courseid","in":"query","required":false,"description":"The course ID for the calendar event.","schema":{"type":"string"}},{"name":"modified","in":"query","required":false,"description":"All events in the classroom calendar that was modified after the date(yyyy-mm-dd format) will be returned.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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"
        }
      ]
    }
  }]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/event/participants":{"get":{"tags":["Classroom Event"],"summary":"Get Event Participants","description":"This API endpoint gets all classroom event participants.","operationId":"event-participants","parameters":[{"name":"fromdate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date"}},{"name":"todate","in":"query","required":false,"description":"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.","schema":{"type":"string","format":"date"}},{"name":"onlynotapproved","in":"query","required":false,"description":"All event participants that have not been approved yet. If notonlyapproved is left blank, then all participants are returned.\n\nAccepted values: **0** / **1**","schema":{"type":"number"}},{"name":"courseid","in":"query","required":false,"description":"The course ID set up for the online course and specific to each company.","schema":{"type":"string"}},{"name":"coursename","in":"query","required":false,"description":"The course ID for the calendar event.","schema":{"type":"string"}},{"name":"eventid","in":"query","required":false,"description":"System event ID where new participants will be created.","schema":{"type":"number"}},{"name":"includeallparticipants","in":"query","required":false,"description":"This parameter is used to include all participants including inactive participants in the response.\n\nAccepted values: **0** / **1**","schema":{"type":"number"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
    "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"
        }
    ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"patch":{"tags":["Classroom Event"],"summary":"Patch Event Participants","description":"This API endpoint can be used to patch event participants.","operationId":"patch-participants","requestBody":{"required":true,"description":"A JSON object structure (field and and value combination) to update the participants' statuses.\n\n* **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.\n* **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:\n  * Pass\n  * Fail\n  * Absent\n* **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.\n* **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.\n* **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.","content":{"application/json":{"schema":{"type":"array"},"example":[
    {
        "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"
    }
]}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
    "success": 1,
    "participantData": [
        {
            "success": 1,
            "id": 621781
        },
        {
            "success": 1,
            "id": 621782
        }
    ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Classroom Event"],"summary":"Add Event Participants","description":"This API endpoint can be used to add new event participants.","operationId":"post-participants","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"eventid":{"type":"string","description":"System event ID where new participants will be created. Event ID can encrypted or decrypted."},"allowmultireg":{"type":"number","description":"Allow participants to be added to be registered for multiple events for the same course.\n\nAccepted values: **0** / **1**"}},"required":["eventid"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
    "success": 1,
    "eventid": "137142",
    "participants": [
        {
            "success": 1,
            "userid": "BIS0001605"
        },
        {
            "success": 0,
            "userid": "BIS0001367",
            "error": "event_full",
            "error_description": "Classroom event is full"
        }
    ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/user/token":{"post":{"tags":["Single Sign-On (SSO)"],"summary":"Custom SSO","description":"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.\n\n1. 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.\n2. The API accepts user parameters as JSON objects.\n3. Upon successfully validating the user, the API will return a JSON Web Token (**JWT**) token that must be used within 30 seconds.\n4. Use the JWT token to redirect the user to the URL: `https://www.bissafety.app/sso/redirect/?token={JWT_TOKEN}`\n\n**Note:** If you are using the system's CUSTOM URL feature, then please replace `www.bissafety.app` with your custom domain.","operationId":"sso-custom","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"user":{"type":"string","description":"This parameter is an array of user objects in JSON format. A maximum number of 200 users can be imported at a time.","examples":["{\r\n  \"userid\": \"String - Required - Unique userid in third party system\",\r\n  \"givenName\": \"String - Required\",\r\n  \"middlename\": \"String - Optional\",\r\n  \"surname\": \"String - Required\",\r\n  \"location\": \"String - OPTIONAL - If location is not provided then new users will be added under default location\",\r\n  \"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\",\r\n  \"role\": \"String - OPTIONAL\",\r\n  \"emailAddress\": \"String - Recommended\",\r\n  \"address\": \"String - Optional\",\r\n  \"city\": \"String - Optional\",\r\n  \"country\": \"String - Optional\",\r\n  \"province\": \"String - Optional\",\r\n  \"postalcode\": \"String - Optional\",\r\n  \"manager\": \"String - Optional - Unique userid in third party system\",\r\n  \"managerEmail\": \"String - manager's email\",\r\n  \"language\": \"String - Optional - Default English\",\r\n  \"startDate\": \"Date - Optional - YYYY-MM-DD Date format\",\r\n  \"SubCompanyName\": \"String - Optional - Only needed when a company has sub companies and want user to login to sub company\",\r\n  \"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.\"\r\n}"]}},"required":["user"]}}}},"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/training/verification":{"get":{"tags":["Open API"],"summary":"Training Verification","description":"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.\n\nThe status of training verification can have one of the following values:\n\n* valid\n\n* invalid - *did not find the matching training*\n\n* expired - *training expired*\n\n* unverified - *if the training was virtually proctored, then 'unverified' means the training was not verified*","operationId":"training-verification","parameters":[{"name":"id","in":"query","required":true,"description":"The ID of the certificate that needed to be verified.","schema":{"type":"string"}},{"name":"lastname","in":"query","required":true,"description":"Last name of the user who completed the training.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "status": "valid",
  "coursename": "COURSE_NAME",
  "expirydate": "YYYY-MM-DD",
  "completiondate": "YYYY-MM-DD"
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"clientId":[],"clientSecret":[]}]}},"/training/networkpartners":{"get":{"tags":["Open API"],"summary":"Network Partners","description":"This API can be used to fetch public network partners from BIS Safety Software.","operationId":"network-parteners","responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "status": "success",
  "networkparteners": [
    "Network Partner 1",
    "Network Partner 2",
    "Network Partner 3",
    "Network Partner 4",
    "Network Partner 5"
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"clientId":[],"clientSecret":[]}]}},"/reward/points":{"get":{"tags":["Rewards"],"summary":"Get Reward Points","description":"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.","operationId":"get-reward-points","parameters":[{"name":"userid","in":"query","required":false,"description":"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.","schema":{"type":"string"}},{"name":"bisinternaluserid","in":"query","required":false,"description":"System ID of a user in BIS.","schema":{"type":"number"}},{"name":"username","in":"query","required":false,"description":"The username of the user's BIS account.","schema":{"type":"string"}},{"name":"email","in":"query","required":false,"description":"The email address in the profile account of the user.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"A filter to get users with a certain status. By default, the API returns active users only \"A\". Use \"I\" to get inactive users.\n\nAccepted values: **A** / **I**","schema":{"type":"string","default":"A"}},{"name":"includesubcompany","in":"query","required":false,"description":"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.\n\nAccepted values: **0** / **1**","schema":{"type":"number","default":0}},{"name":"offset","in":"query","required":false,"description":"Offset the results by a certain value. By default, the offset is zero \"0\".","schema":{"type":"number","default":0}},{"name":"recordsperpage","in":"query","required":false,"description":"Limit the number of users that are returned up to a maximum of 500. A larger value is trimmed to 500.","schema":{"type":"number","default":500}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "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
    }
  ]
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Rewards"],"summary":"Update Reward Points","description":"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.","operationId":"update-reward-points","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"points":{"type":"number","description":"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":{"type":"string","description":"The User ID of the user in your system. Supply exactly one of userid, bisinternaluserid, username or email."},"bisinternaluserid":{"type":"number","description":"System ID of a user in BIS. Supply exactly one of userid, bisinternaluserid, username or email."},"username":{"type":"string","description":"The username of the user's BIS account. Supply exactly one of userid, bisinternaluserid, username or email."},"email":{"type":"string","description":"The email address in the profile account of the user. Supply exactly one of userid, bisinternaluserid, username or email."},"reason":{"type":"string","default":"Reward point total updated through API","description":"Text stored with the point adjustment and shown in the user's point history and the notification email."},"notify":{"type":"number","default":0,"description":"Send the reward notification email to the user when the total changes by specifying \"1\". By default no email is sent \"0\".\n\nAccepted values: **0** / **1**"},"includesubcompany":{"type":"number","default":0,"description":"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.\n\nAccepted values: **0** / **1**"}},"required":["points"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{
  "userid": "EMP1042",
  "bisinternaluserid": 123456,
  "previouspoints": 300,
  "points": 50,
  "adjustment": -250
}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Token from POST /token"},"clientId":{"type":"apiKey","in":"header","name":"client_id"},"clientSecret":{"type":"apiKey","in":"header","name":"client_secret"}},"responses":{"BadRequest":{"description":"A required parameter or header is missing or not valid."},"Unauthorized":{"description":"The bearer token, or the client_id and client_secret, is not valid or has expired."},"Forbidden":{"description":"The API credential does not have access to this endpoint."}}}}