Getting started
API Access is a paid add-on, available on every plan and priced by the size of your plan. Once it is on your account:
- An Admin-level user goes to Settings > API Access and creates a key for each system they want to connect, choosing what it may do.
- The key is shown once. Copy it into the other system's secure settings.
- Send it with every call. All addresses start
https://www.assuraz.co.uk/api/v1, and every call only ever sees your own company's data.
Calls use HTTPS and JSON. Dates are yyyy-mm-dd; times are UTC. GET /api/v1 lists everything the API offers.
Authentication
Send the key in the Authorization header (or an X-API-Key header if your tool can't set Authorization):
Authorization: Bearer azk_XXXXXXXX_your-keyEach key has one or more permissions:
read | Read employees, training, incidents, actions, non-conformities, risks, objectives, audits, contractors and suppliers (for Power BI, Excel and other reporting). |
employees:write | Add and update employees and record leavers from your HR system or Active Directory. |
training:write | Record completed training, with its certificate, from another e-learning or training system (e.g. iHASCO). |
Keys can be given an expiry date and revoked at any time in Settings > API Access; a revoked key stops working straight away.
Rate limits
Limits are per company (shared by all its keys) and follow the size of your plan:
| Plan size | Requests a minute | Requests a day |
|---|---|---|
| Lite (up to 15 employees) | 60 | 5,000 |
| Standard (up to 60 employees) | 120 | 15,000 |
| Enterprise 1 (up to 150 employees) | 180 | 30,000 |
| Enterprise 2 (up to 300 employees) | 240 | 50,000 |
| Enterprise 3 (up to 450 employees) | 300 | 75,000 |
| Enterprise 4 (up to 600 employees) | 450 | 100,000 |
| Larger or custom plans | 600 | 150,000 |
- The daily count resets at midnight UTC.
- A page holds up to 2,000 rows (default 500); a sync call up to 1,000 employees or training records; a request body up to 2 MB.
- Every response tells you where you are:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(seconds),X-RateLimit-Daily-LimitandX-RateLimit-Daily-Remaining. - Over a limit, the call is refused with
429and aRetry-Afterheader (seconds). Wait and try again. - A nightly refresh of a few registers uses a few dozen requests: the limits are there to keep the service fast for everyone, not to get in the way of normal reporting.
Reading data
GET /api/v1/<register> returns one page of a register. Needs the read permission.
| Address | What it returns | Date filter |
|---|---|---|
/api/v1/employees | Everyone on the Employee Register, with their department, location and manager. Is_Current is 1 for people employed today. | Employment_Start_Date |
/api/v1/locations | Your locations (offices, sites) with their address and contact details. | - |
/api/v1/departments | Your departments. | - |
/api/v1/courses | The Master Course List. | - |
/api/v1/training-records | Every training record, with the employee and course, and whether it is valid, expiring soon (within 60 days) or expired. | Date_Completed |
/api/v1/incidents | Incidents, accidents and near misses, with category, type and location. | Incident_Date |
/api/v1/non-conformities | Non-conformities, complaints and other issues, with status, owner and dates. | Date_Raised |
/api/v1/actions | Corrective and improvement actions from every module, with who they are assigned to and when they are due. | Due_Date |
/api/v1/risks | The Risk and Opportunities Register, with initial and residual scores. | - |
/api/v1/objectives | Objectives and KPIs with their targets. | - |
/api/v1/objective-results | The monthly results for each objective or KPI (one row per KPI per month). | MeasurementPeriod |
/api/v1/audits | Internal and external audits, with planned and completed dates and status. | Planned_Date |
/api/v1/contractors | The Contractor Register (no bank details). | - |
/api/v1/suppliers | The Supplier Register. | - |
Options
page | Page number, from 1. |
pageSize | Rows per page, up to 2,000 (default 500). |
updatedSince | Only rows added or changed since this date, for registers that record it. The reply includes a note if a register doesn't. |
from, to | On or after / on or before a date, on the register's main date (shown above). |
includeInactive | true to include deleted (inactive) rows. |
format | csv for a CSV file (opens in Excel) instead of JSON. |
curl -H "Authorization: Bearer azk_XXXXXXXX_your-key" \
"https://www.assuraz.co.uk/api/v1/training-records?pageSize=500&page=1"{
"resource": "training-records",
"page": 1,
"pageSize": 500,
"total": 1284,
"hasMore": true,
"next": "/api/v1/training-records?pageSize=500&page=2",
"data": [
{
"ID_TrainingRecord": 5521,
"ID_Employee": 88,
"ID_Course": 12,
"Date_Completed": "2026-03-14T00:00:00.000Z",
"Expiry_Date": "2029-03-14T00:00:00.000Z",
"Staff_ID": "1042",
"First_Name": "Sophie",
"Last_Name": "Brown",
"Employee_Email": "sophie.brown@example.co.uk",
"Course_Title": "Emergency First Aid at Work",
"Training_Status": "Valid"
}
]
}Rows are ordered by their ID, so paging is stable. Keep requesting next until hasMore is false. Columns are the register's own, plus friendly names from related tables (category, location, person); new columns appear as Assuraz grows, so build reports on the names you use rather than column positions. For privacy the API never returns files, signatures, bank or tax details, or diversity information (gender, ethnicity, disability).
Power BI and Excel
Power BI Desktop
- Home > Get data > Blank query, then Advanced editor.
- Paste the query below, put in your key and the register you want (incidents, training-records, actions…), and choose Done.
- If asked how to connect, choose Anonymous (the key is in the query). Repeat for each register and relate them on their ID columns (e.g. ID_Employee).
- Publish to the Power BI service and set a scheduled refresh; the query fetches every page each time.
let
// Your API key (Settings > API Access in Assuraz) and the register you want
Key = "azk_XXXXXXXX_your-key",
Url = "https://www.assuraz.co.uk/api/v1/incidents",
GetPage = (page as number) =>
Json.Document(Web.Contents(Url, [
Query = [page = Text.From(page), pageSize = "2000"],
Headers = [Authorization = "Bearer " & Key]
])),
Pages = List.Generate(
() => [n = 1, r = GetPage(1)],
each [r] <> null,
each if [r][hasMore] then [n = [n] + 1, r = GetPage([n] + 1)] else [n = [n], r = null],
each [r][data]
),
Rows = List.Combine(Pages),
Result = Table.FromRecords(Rows, null, MissingField.UseNull)
in
ResultExcel
The same query works in Excel: Data > Get Data > From Other Sources > Blank Query > Advanced Editor, paste, Close & Load, then Data > Refresh All whenever you want the latest figures. For a quick one-off, Data > From Web > Advanced, with the address https://www.assuraz.co.uk/api/v1/incidents?format=csv&pageSize=2000 and an HTTP request header Authorization = Bearer your-key.
Keep the key out of shared workbooks: anyone with the file can read the query. For shared reports, use Power BI with the key held by the report owner.
Power Automate
Add Assuraz to Power Automate (and Power Apps) as a custom connector. You then get ready-made actions such as List incidents, List training records, Sync employees and Add training completions, with every field available as dynamic content in your flows. Custom connectors need a Power Automate premium licence.
Set up the connector (once per organisation)
- Download the Assuraz connector file.
- In Power Automate, go to Data > Custom connectors (under More if you can't see it), then New custom connector > Import an OpenAPI file.
- Name it Assuraz, choose the file you downloaded, and select Continue.
- On the General tab you can add the Assuraz icon and a background colour. On the Security tab check it says API Key, with the parameter name
X-API-Keyin the header. Give the label a friendly name such as Assuraz API key. - Select Create connector. You can share the connector with colleagues from its menu.
Use it in a flow
- Add an action, choose the Custom tab and pick Assuraz.
- The first time, create a connection and paste an API key from Settings > API Access exactly as shown (no “Bearer”). Use a key with only the permissions the flow needs.
- For the List actions, open the action's Settings and turn on Pagination (set a threshold such as 5,000) to get every page, or use Changed since to fetch only recent changes.
- Loop over the results with Apply to each on the register's list (for example Incidents), and use its fields in later steps.
Ideas
- Every morning, post incidents reported since yesterday to a Microsoft Teams channel.
- Every Monday, email each manager the training records in their team that are Expiring soon or Expired.
- When a row is added to an Excel or SharePoint list of new starters, add them with Sync employees.
- When your e-learning system (for example iHASCO) emails a completion certificate, record the training and attach the certificate with Add training completions: see Training completions.
Flows that start the moment something happens in Assuraz (for example “when an incident is reported”) are coming later. For now, run flows on a schedule and use Changed since.
Employee sync (HR systems and Active Directory)
POST /api/v1/sync/employees adds and updates employees and records leavers. Needs the employees:write permission. Run it from your HR system's integration tools, Power Automate, or a scheduled script, typically nightly.
- Each employee is matched on
staffId, thenemail. A match is updated; anyone new is added (within your plan's employee limit) and asked to sign your declarations, as when added on screen. - Only the fields you send are changed; send
nullto clear one. Fields: staffId, email, firstName, lastName, jobTitle, telephone, department, location, managerStaffId or managerEmail, workingPattern (Office Based, Home Based, Field Based, Hybrid Worker), startDate, leavingDate. - A department that doesn't exist yet is added (send
"createDepartments": falseto stop this). Locations must already exist in Assuraz; an unknown one is reported as a warning. - Send
leavingDatefor a leaver. Or, if each call sends your complete list of current staff, add"markMissingAsLeavers": trueand everyone not in the list is marked as leaving today (or onleavingDate). As a safeguard, a change that would mark more than a quarter of current employees as leavers is refused unless you also send"confirmLargeLeaverChange": true. - The reply lists what happened to every row; a bad row never stops the others.
POST https://www.assuraz.co.uk/api/v1/sync/employees
Authorization: Bearer azk_XXXXXXXX_your-key
Content-Type: application/json
{
"employees": [
{
"staffId": "1042",
"email": "sophie.brown@example.co.uk",
"firstName": "Sophie",
"lastName": "Brown",
"jobTitle": "IT Manager",
"department": "IT",
"location": "Stockport Office",
"managerEmail": "james.okafor@example.co.uk",
"workingPattern": "Hybrid Worker",
"startDate": "2024-02-05"
},
{ "staffId": "0977", "leavingDate": "2026-10-31" }
],
"markMissingAsLeavers": false
}{
"created": 1, "updated": 1, "unchanged": 0, "leavers": 0, "errors": 0,
"results": [
{ "row": 1, "staffId": "1042", "action": "created", "id": 311 },
{ "row": 2, "staffId": "0977", "action": "updated", "id": 154, "changed": ["Termination_Date"] }
]
}Example: Active Directory, nightly
# Run on a server with the ActiveDirectory PowerShell module, e.g. as a nightly scheduled task.
$Key = 'azk_XXXXXXXX_your-key' # better: read it from a secure store, not the script
$Uri = 'https://www.assuraz.co.uk/api/v1/sync/employees'
$users = Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Staff,DC=example,DC=local' `
-Properties EmployeeID, Mail, GivenName, Surname, Title, Department, Office, TelephoneNumber, Manager
$rows = foreach ($u in $users) {
$managerMail = $null
if ($u.Manager) { $managerMail = (Get-ADUser $u.Manager -Properties Mail).Mail }
[ordered]@{
staffId = $u.EmployeeID; email = $u.Mail; firstName = $u.GivenName; lastName = $u.Surname
jobTitle = $u.Title; department = $u.Department; location = $u.Office
telephone = $u.TelephoneNumber; managerEmail = $managerMail
}
}
# Up to 1000 employees per call
for ($i = 0; $i -lt $rows.Count; $i += 1000) {
$batch = $rows[$i..([Math]::Min($i + 999, $rows.Count - 1))]
$body = @{ employees = @($batch) } | ConvertTo-Json -Depth 4
$result = Invoke-RestMethod -Method Post -Uri $Uri -Headers @{ Authorization = "Bearer $Key" } `
-ContentType 'application/json; charset=utf-8' -Body ([Text.Encoding]::UTF8.GetBytes($body))
"Created $($result.created), updated $($result.updated), errors $($result.errors)"
}For Microsoft Entra ID (Azure AD) or an HR system such as BambooHR, Personio, Sage HR or Cezanne, use the same call from Power Automate, Logic Apps or the system's own webhooks or scheduled exports. Ask us if you would like help.
Training completions
POST /api/v1/sync/training-records records training completed on another platform (an e-learning system, a training provider's portal). Needs the training:write permission.
- Identify the employee by
employeeStaffId,employeeEmailoremployeeId, and the course bycourseIdor its exactcourseTitleon your Master Course List (add"createCourses": trueto add unknown courses). dateCompletedis required;expiryDateis optional.- A completion already recorded (same employee, course and date) is skipped, so it is safe to send the same records again.
- Certificates: add
certificateContent(the file, base64-encoded),certificateFileNameand, if you know it,certificateContentType. PDF, PNG, JPEG, GIF or WebP, up to 5 MB each and 25 MB per request. The certificate is attached to the training record, so View certificate on the Skills Matrix and Training Records opens it. - Sending a certificate for a completion that is already recorded adds it to that record if it has none. Add
"replaceCertificate": trueto replace one that is already there. - If a certificate can't be saved (not a PDF or image, too large, or the company's storage allowance is full), the completion is still recorded and that row's
certificateresult says why.
POST https://www.assuraz.co.uk/api/v1/sync/training-records
Authorization: Bearer azk_XXXXXXXX_your-key
Content-Type: application/json
{
"records": [
{ "employeeEmail": "sophie.brown@example.co.uk", "courseTitle": "Fire Safety Awareness", "dateCompleted": "2026-10-20" },
{ "employeeStaffId": "1042", "courseId": 12, "dateCompleted": "2026-10-21", "expiryDate": "2029-10-21" },
{
"employeeEmail": "tom.reid@example.co.uk",
"courseTitle": "Manual Handling",
"dateCompleted": "2026-10-22",
"certificateFileName": "Manual-Handling-certificate.pdf",
"certificateContentType": "application/pdf",
"certificateContent": "JVBERi0xLjcKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFI..."
}
]
}Certificates from iHASCO and other online training providers
Using iHASCO? You don't need Power Automate. Paste your iHASCO API key on Settings > API Access > iHASCO training and Assuraz brings in each pass with its certificate every morning. The steps below are for other providers.
Most providers, iHASCO included, issue a certificate as soon as a course is passed and email it to the learner or the training administrator. Power Automate can pass each one straight to Assuraz:
- Have the provider send certificate emails to one mailbox (or forward them there with an Outlook rule).
- In Power Automate, start a flow with When a new email arrives (V3) on that mailbox, filtered to the provider's sender and Only with attachments.
- Work out who and what from the email (the subject or body usually has the learner's name or email and the course title). Or send the learnerGet employees from Assuraz can turn a name into a staff ID.apos;s email as
employeeEmail; List employees from Assuraz can turn a name into a staff ID. - Add the Assuraz action Add training completions with the employee, course title, completion date (the email's received date is usually right), and for the certificate the attachment's Name, Content type and Content Bytes.
If your provider offers an API with results (iHASCO's Client API does, with an access token from your iHASCO account), a scheduled flow can also send completions without waiting for the emails. Ask us if you would like help setting up either.
Errors
400 | Something in the request isn't right; the message says what. |
401 | Missing, unknown, revoked or expired key. |
403 | The add-on isn't active, the key lacks the permission, or the account is read-only (suspended or expired subscriptions can still read but not write). |
404 | Unknown address or register. |
409 | A large leaver change that needs confirming. |
413 | The request is too large; send smaller batches. |
429 | Rate limit reached; wait for Retry-After seconds. |
500 | Something went wrong on our side; try again, and contact support if it continues. |
Errors come back as JSON: { "error": "What went wrong" }.
Security and data protection
- Keys are stored only as a one-way hash; we can't read them back. Every call is over HTTPS and limited to the key's company.
- Every call is logged (key, address, result, time), and the latest calls and usage are shown in Settings > API Access.
- You are the controller of the data you take out through the API. Once it is in another system (a Power BI report, a spreadsheet, your HR system), protecting it there is your responsibility, as set out in our terms.
- Version 1 won't change in ways that break your integrations: new registers and columns may be added, and we will give at least six months' notice before retiring anything.
Questions about the API: contact your Assuraz account manager or use the Contact page.