All Wellbeing APIs

Customer Reporting API

A secure, read-only way to pull wellbeing and office-ergonomics reporting about your people, organised by group.

Version 5.5.0 Updated 2026-08-31 Full technical reference OpenAPI specification
Available on enterprise Wellbeing sites.
Data out. A secure, read-only way to pull wellbeing and office-ergonomics reporting about your people, organised by group.Read-only. This API never changes anything in Wellbeing.
Your systems BI, intranet or HR dashboards that want the data
Access token Bearer authorisation plus your site's tenant header
Customer Reporting API Read-only GET calls under /v1/echo

Your groups

Which teams and groups exist in our organisation?

An unpaginated call returning every group you can report on.

Group name Group ID Type Category Access level Origin

Wellbeing reports

How is everyone in this group tracking on wellbeing?

A per-person scorecard across four everyday areas, each a rating plus a number.

Overall wellbeing Computer use Breaks Sit-stand
Rating Score
First name Last name Unique ID Data date Last sync First sync Account created App version User ID
Total count

Assessment status

Where is each person up to with their ergonomic assessments?

A status board across the four assessment types, with eleven filters so you can ask for just the exceptions.

Assessment type Switched on? Due Scheduled Last completed Expires Overdue? Expired? Ever completed? Self-started?
Name Email Unique ID User ID
Total count

Training status

Who has done their ergonomics training, and who is behind?

The same shape as assessment status, for the single ergonomics training.

Switched on? Due Scheduled Last completed Overdue? Ever completed?
Name Email Unique ID User ID
Total count

Combined ergonomics report

Deprecated

Assessments and training in one call - the older way.

Returns assessments and training together with no filters and no totalCount; use the two endpoints above instead.

Name Email Unique ID User ID Assessments Training
Hover or focus any field for what it means, its type and an example value Each call links to that operation in the technical reference A dashed field marked ? has no plain-language description yet

Steps 1 to 5 must be completed by an administrator in your Wellbeing site. Steps 6 onwards are for the developer who will build your integration.

1

Check the API is available on your site

Administrator

API access tokens are an enterprise feature and are switched on per site by Wellnomics. Sign in and look for Admin → API access tokens. If it is not there, contact Wellnomics Support and ask for API access tokens to be enabled.

2

Sign in as an administrator

Administrator

You need the Wellnomics Administrator right to create or revoke API tokens.

3

Create a Customer Reporting token

Administrator

Go to Admin → API access tokens and choose Create. Set the type to Customer Reporting. Give it a name that says what will use it - 3 to 100 characters, letters, numbers, hyphen and underscore only, and unique among your active tokens. Pick an expiry: 1, 7, 30, 90 or 180 days, or never.

We recommend using an expiry rather than never, just make sure you remember to come back and create a new token before the old one runs out. Communicate the expiry date to your developer. We also recommend creating one token per consuming system. When something needs revoking you then take down one integration, not all of them.
4

Copy the token now

Administrator

The token is displayed once, on creation. It cannot be retrieved afterwards - if you lose it, revoke it and create another.

This token grants read access to reporting data for your whole organisation, including names and email addresses. Hand it over only to your development team and through a password manager or secret store, never by email or chat, and always communicate the expiry date, if set.
5

Ask Wellnomics Support for your base URL

Administrator

The API is served from the regional server that hosts your site, so the base URL cannot be worked out from the address you sign in at - email support@wellnomics.com and we will give you the one for your site. The tenant header is a different value: the hostname you sign in at, for example acme.wellnomics.com.

6

Make your first call: list the groups

Developer

Call GET /v1/echo/groups with both headers. It is unpaginated and a good way to prove your token, your tenant header and your network path all work before you touch a reporting endpoint.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$headers = @{
    Authorization = "Bearer $env:WELLNOMICS_API_TOKEN"
    tenant        = 'acme.wellnomics.com'
}

$groups = Invoke-RestMethod -Method GET `
    -Uri 'https://api.your-region.wellnomics.com/v1/echo/groups' `
    -Headers $headers

$groups.data | Sort-Object name | Format-Table id, name, groupType
A 401 here means the token is wrong, expired, or sent with the wrong scheme - it must be exactly Bearer <token>. A missing or misspelled tenant header gives a 400 instead.
7

Pick a group and pull a report

Developer

Take an id from step 6 - usually the group with groupType 4, which will be the everyone group for your organisation - and call a reporting endpoint with it. Remember limit and offset are required. Read totalCount in the response and keep paging until you have collected that many rows.

$groupId = 4
$uri = "https://api.your-region.wellnomics.com/v1/echo/groups/$groupId/ergonomics-training-reports?limit=500&offset=0&overdue=true"

$page = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers

"{0} of {1} people are overdue" -f $page.data.Count, $page.totalCount
$page.data | Select-Object name, email, @{n='dueDate';e={$_.training.dueDate}}
8

Send filters defensively

Developer

Boolean filters are booleans: send true or false. Lowercase is the form to write, though the server matches case-insensitively, so True from .NET or Python works too — you do not need to normalise before sending. What does matter: build the query string so an unset filter is left out altogether rather than appended empty — ?overdue= is a 400, not "no filter".

# Build the query from only the filters that are actually set, so an
# unset one is absent rather than empty.
$filters = @{ limit = 500; offset = 0 }
if ($PSBoundParameters.ContainsKey('Overdue')) { $filters.overdue = $Overdue.ToString().ToLower() }

$query = ($filters.GetEnumerator() | ForEach-Object {
    "{0}={1}" -f [Uri]::EscapeDataString($_.Key), [Uri]::EscapeDataString([string]$_.Value)
}) -join '&'

$uri = "https://api.your-region.wellnomics.com/v1/echo/groups/4/ergonomics-training-reports?$query"
9

Plan for rotation before you go live

Developer

When logged in to the Wellbeing site your administrators will see a banner 14 days before a token expires, and an error banner once it has. Do not rely on spotting it: put the expiry date in a calendar and ensure your integration treats a 401 as 'get a new token', not as a fatal crash. The sample scripts show one way to do that.

GET /v1/echo/groups Get a list of all existing groups in the system

Parameters

Name Sent as Required Type What it does
tenant — Your site hostname header Required string Sent as a header on every request. Use the hostname you sign in at, e.g. acme.wellnomics.com. Resolved before authentication, so a wrong value returns 400 even with a valid token.

Returns — 200

Field Type What it does
data[].id integer Unique identifier for the group.
data[].groupType integer (enum) How the group is put together.
2 Direct3 AllStaffUnderMe4 Everyone5 Custom
data[].groupCategory integer (enum) How the group's membership is maintained.
1 System2 Static3 Dynamic
data[].groupAccess integer (enum) Whether the group is private to the person who created it or shared with administrators.
1 Owner2 RestrictedAdmin
data[].name string The group's display name - what the team or unit is called in Wellbeing.
data[].userGroupCategory string Where the group came from: `System`, `Organisation`, `LocalAdministration` or `Personal`.

Possible errors

401 403 500

Full technical reference

GET /v1/echo/groups/{groupId}/ergonomics-assessments-reports Get a list of the office ergonomics assessments reporting data of each user of the given group

Parameters

Name Sent as Required Type What it does
groupId — Group ID path Required string Which group to report on. Get it from GET /v1/echo/groups.
tenant — Your site hostname header Required string Sent as a header on every request. Use the hostname you sign in at, e.g. acme.wellnomics.com. Resolved before authentication, so a wrong value returns 400 even with a valid token.
limit — Page size query Required integer Required. How many records to return, 1 to 2000. Larger pages mean fewer calls; 1000 is a sensible default.
offset — Skip query Required integer Required. How many records to skip. Start at 0, then add your page size for each subsequent page.
type — Assessment type filter query Required string Limit results to one or more assessment types. Repeat the parameter for several types. Omit for all types.
hasEverCompleted — Ever completed filter query Optional boolean true returns only people who have completed at least once; false returns only people who never have. Set false to build a 'never started' list.
overdue — Overdue filter query Optional boolean true returns only overdue records. This is the intended way to build a compliance chase-up list.
expired — Expired filter query Optional boolean true returns only assessments whose completion has passed its expiry date and needs redoing.
Omit the parameter entirely to mean "no filter". Sending it empty (?expired=) is a 400, not an absent filter.
enabled — Switched-on filter query Optional boolean true limits results to assessments or training actually switched on for the person. Use it to avoid reporting on things nobody is expected to do.
includeOnDemandAssessments — Include self-started query Optional boolean Defaults to false. When false, assessments a person started themselves are treated as not done. Leave it off for scheduled-compliance reporting; turn it on to see all activity.
Omit the parameter entirely to mean "no filter". Sending it empty (?includeOnDemandAssessments=) is a 400, not an absent filter.
lastCompletedDate.before — Completed before query Optional string (date) Plain date, YYYY-MM-DD. Returns records last completed before this date - the way to find people whose last completion is going stale.
lastCompletedDate.after — Completed after query Optional string (date) Plain date, YYYY-MM-DD. Returns records last completed after this date - the way to report on activity in a period.
lastCompletedDate.isNull — Never completed query Optional boolean true returns only records with no completion date at all. false returns only those with one.
Omit the parameter entirely to mean "no filter". Sending it empty (?lastCompletedDate.isNull=) is a 400, not an absent filter.

Returns — 200

Field Type What it does
data[].userId integer The internal identifier for this record.
data[].uniqueId string The person's identifier from your own HR system.
data[].name string The person's first and last name as a single value.
data[].email string The person's email address.
data[].assessments[].type string (enum) Which of the four ergonomic assessments this row is about.
PostureAndWorkstationWorkEnvironmentDiscomfortIndividual
data[].assessments[].enabled boolean Whether this assessment or training is switched on for the person.
data[].assessments[].dueDate string (date-time), nullable The date this is due to be completed by.
data[].assessments[].scheduledDate string (date-time), nullable When this assessment or training was created for the person.
data[].assessments[].expiryDate string (date-time), nullable When a completed assessment stops counting as current.
data[].assessments[].lastCompletedDate string (date-time), nullable When the person last completed this.
data[].assessments[].overdue boolean Whether this is past its due date and still not done.
data[].assessments[].onDemand boolean, nullable True when the person started this assessment themselves rather than being scheduled for it.
data[].assessments[].expired boolean Whether a previously completed assessment has passed its expiry date and needs doing again.
data[].assessments[].hasEverCompleted boolean Whether the person has ever completed this, at any point.
totalCount integer How many records exist in total, before limit and offset are applied.

Possible errors

400 401 403 404 500

Full technical reference

GET /v1/echo/groups/{groupId}/ergonomics-training-reports Get a list of the ergonomics training reporting data of each user of the given group

Parameters

Name Sent as Required Type What it does
groupId — Group ID path Required string Which group to report on. Get it from GET /v1/echo/groups.
tenant — Your site hostname header Required string Sent as a header on every request. Use the hostname you sign in at, e.g. acme.wellnomics.com. Resolved before authentication, so a wrong value returns 400 even with a valid token.
limit — Page size query Required integer Required. How many records to return, 1 to 2000. Larger pages mean fewer calls; 1000 is a sensible default.
offset — Skip query Required integer Required. How many records to skip. Start at 0, then add your page size for each subsequent page.
hasEverCompleted — Ever completed filter query Optional boolean true returns only people who have completed at least once; false returns only people who never have. Set false to build a 'never started' list.
overdue — Overdue filter query Optional boolean true returns only overdue records. This is the intended way to build a compliance chase-up list.
enabled — Switched-on filter query Optional boolean true limits results to assessments or training actually switched on for the person. Use it to avoid reporting on things nobody is expected to do.
lastCompletedDate.before — Completed before query Optional string (date) Plain date, YYYY-MM-DD. Returns records last completed before this date - the way to find people whose last completion is going stale.
lastCompletedDate.after — Completed after query Optional string (date) Plain date, YYYY-MM-DD. Returns records last completed after this date - the way to report on activity in a period.
lastCompletedDate.isNull — Never completed query Optional boolean true returns only records with no completion date at all. false returns only those with one.
Omit the parameter entirely to mean "no filter". Sending it empty (?lastCompletedDate.isNull=) is a 400, not an absent filter.

Returns — 200

Field Type What it does
data[].userId integer The internal identifier for this record.
data[].uniqueId string The person's identifier from your own HR system.
data[].name string The person's first and last name as a single value.
data[].email string The person's email address.
data[].training.enabled boolean Whether this assessment or training is switched on for the person.
data[].training.dueDate string (date-time), nullable The date this is due to be completed by.
data[].training.scheduledDate string (date-time), nullable When this assessment or training was created for the person.
data[].training.lastCompletedDate string (date-time), nullable When the person last completed this.
data[].training.overdue boolean Whether this is past its due date and still not done.
data[].training.hasEverCompleted boolean Whether the person has ever completed this, at any point.
totalCount integer How many records exist in total, before limit and offset are applied.

Possible errors

400 401 403 404 500

Full technical reference

GET /v1/echo/groups/{groupId}/reports Get a list of the management reporting data of each user of the given group

Parameters

Name Sent as Required Type What it does
groupId — Group ID path Required string Which group to report on. Get it from GET /v1/echo/groups.
tenant — Your site hostname header Required string Sent as a header on every request. Use the hostname you sign in at, e.g. acme.wellnomics.com. Resolved before authentication, so a wrong value returns 400 even with a valid token.
limit — Page size query Required integer Required. How many records to return, 1 to 2000. Larger pages mean fewer calls; 1000 is a sensible default.
offset — Skip query Required integer Required. How many records to skip. Start at 0, then add your page size for each subsequent page.

Returns — 200

Field Type What it does
data.groupReport[].id integer The internal identifier for this record.
data.groupReport[].uniqueId string The person's identifier from your own HR system.
data.groupReport[].firstName string The person's first name.
data.groupReport[].lastName string The person's last name.
data.groupReport[].accountCreated string (date-time) When the person's Wellbeing account was created.
data.groupReport[].firstSync string (date-time), nullable The first time the person's Wellnomics app sent data in.
data.groupReport[].lastSync string (date-time), nullable The last time the person's app sent data in.
data.groupReport[].clientVersion string, nullable The version of the Wellnomics desktop app the person is running.
data.groupReport[].dataDate string (date-time) The date the wellbeing figures on this row describe.
data.groupReport[].reportData.overallWellbeing.rating string (enum) The overall wellbeing band for this person.
ExcellentGoodFairImproveImproveASAP
data.groupReport[].reportData.overallWellbeing.score number The numeric value behind the rating.
data.groupReport[].reportData.computerUse.rating string (enum) How much computer exposure this person has.
LowModerateHighVeryHigh
data.groupReport[].reportData.computerUse.score number The numeric value behind the rating.
data.groupReport[].reportData.breaks.rating string (enum) How well this person breaks up their computer work.
ExcellentGoodFairPoor
data.groupReport[].reportData.breaks.score number The numeric value behind the rating.
data.groupReport[].reportData.sitStand.rating string (enum) How this person varies between sitting and standing.
ExcellentGoodFairPoor
data.groupReport[].reportData.sitStand.score number The numeric value behind the rating.
totalCount integer How many records exist in total, before limit and offset are applied.

Possible errors

400 401 403 404 500

Full technical reference

GET /v1/echo/groups/{groupId}/ergonomics-report Deprecated Get a list of the office ergonomics reporting data of each user of the given group

Parameters

Name Sent as Required Type What it does
groupId — Group ID path Required string Which group to report on. Get it from GET /v1/echo/groups.
tenant — Your site hostname header Required string Sent as a header on every request. Use the hostname you sign in at, e.g. acme.wellnomics.com. Resolved before authentication, so a wrong value returns 400 even with a valid token.
limit — Page size query Required integer Required. How many records to return, 1 to 2000. Larger pages mean fewer calls; 1000 is a sensible default.
offset — Skip query Required integer Required. How many records to skip. Start at 0, then add your page size for each subsequent page.

Returns — 200

Field Type What it does
data[].userId integer The internal identifier for this record.
data[].uniqueId string The person's identifier from your own HR system.
data[].name string The person's first and last name as a single value.
data[].email string The person's email address.
data[].assessments[].type string (enum) Which of the four ergonomic assessments this row is about.
PostureAndWorkstationWorkEnvironmentDiscomfortIndividual
data[].assessments[].enabled boolean Whether this assessment or training is switched on for the person.
data[].assessments[].dueDate string (date-time), nullable The date this is due to be completed by.
data[].assessments[].scheduledDate string (date-time), nullable When this assessment or training was created for the person.
data[].assessments[].expiryDate string (date-time), nullable When a completed assessment stops counting as current.
data[].assessments[].lastCompletedDate string (date-time), nullable When the person last completed this.
data[].assessments[].overdue boolean Whether this is past its due date and still not done.
data[].assessments[].expired boolean Whether a previously completed assessment has passed its expiry date and needs doing again.
data[].assessments[].hasEverCompleted boolean Whether the person has ever completed this, at any point.
data[].training.enabled boolean Whether this assessment or training is switched on for the person.
data[].training.dueDate string (date-time), nullable The date this is due to be completed by.
data[].training.scheduledDate string (date-time), nullable When this assessment or training was created for the person.
data[].training.lastCompletedDate string (date-time), nullable When the person last completed this.
data[].training.overdue boolean Whether this is past its due date and still not done.
data[].training.hasEverCompleted boolean Whether the person has ever completed this, at any point.

Possible errors

400 401 403 404 500

Full technical reference