Universal Tracker Values
GET /v1/universal-tracker-values
Model interface schema in TypeScript:
interface UniversalTrackerValue {
// Unique Id - ObjectId (24 character hex string)
_id: string,
// Reference to the UniversalTracker, containing metadata information - ObjectId
universalTrackerId: string,
// Reporting level (node) Id - ObjectId
initiativeId: string,
status: 'created' | 'updated' | 'rejected' | 'verified',
// Only allow to create "actual" type of surveys at the moment
utrvType: 'actual',
// Numeric or percentage type answers contains value here
value?: number,
// Complex object containg answer data based on the UniversalTracker valueType
valueData?: {
// Based on valueType it can have different shape of data stored here
// Text: Max 5000 characters, Arrays: Max 100 items
data?: string | string[] | Record<string, string> | Record<string, number>;
// Table data: Max 1000 rows × 50 columns
table?: { code: string, value: string | number}[][];
// Not applicable type: 'na' = Not Applicable, 'nr' = Not Reported
notApplicableType?: 'na' | 'nr';
isImported?: boolean;
},
period: 'monthly' | 'quarterly' | 'yearly',
// Period end date
effectiveDate: Date,
// Determine if evidence is required for underlying Universal Tracker Values
evidenceRequired: boolean,
// Determine if verification step is required for underlying Universal Tracker Values
verificationRequired: boolean,
// Survey Universal Tracker Values default private value
isPrivate?: boolean,
// Only populated when added to assurance process through Assurance Tracker app
assuranceStatus?: 'created' | 'completed' | 'completed_open' | 'rejected' | 'restated' | 'partial',
// Latest notes from stakeholders and verifiers
notes?: {
// Note from the data stakeholder/contributor
stakeholder?: {
date: Date;
action: 'updated';
note?: string;
};
// Note from the data verifier
verifier?: {
date: Date;
action: 'verified' | 'rejected';
note?: string;
};
},
// Metadata information about overall question
universalTracker?: {
_id: string,
type: 'kpi',
valueType: UtrValueType,
unitType?: SupportedMeasureUnits,
unit?: string,
instructions?: string; // Additional instructions for answering the question
valueValidation?: {
min?: number; // For numeric values
max?: number; // For numeric values
valueList?: {
type: 'list',
// ValueList Id to look up available options - ObjectId
listId: string
};
table?: {
validation?: {
maxRows: number; // Default: 1000 rows max
};
columns: {
type: string;
code: string;
name: string; // Max: 500 characters
shortName?: string; // Max: 100 characters
unit?: string;
unitType?: string;
numberScale?: string;
}[];
};
decimal?: number;
},
numberScale?: string,
name: string,
valueLabel: string,
typeCode?: string
}
}
export enum SupportedMeasureUnits {
time = 'time',
area = 'area',
mass = 'mass',
volume = 'volume',
energy = 'energy',
currency = 'currency',
co2Emissions = 'co2Emissions',
partsPer = 'partsPer',
numberScale = 'numberScale',
length = 'length',
}
enum UtrValueType {
// Stored in value property
Number = 'number', // number
Percentage = 'percentage', // number
// Complex types stored in valueData.data (string | string[] | Record)
Text = 'text', // string
Date = 'date', // string
ValueListMulti = 'valueListMulti', // string[]
ValueList = 'valueList', // string
NumericValueList = 'numericValueList', // Record<string, number>
TextValueList = 'textValueList', // Record<string, string>
// Stored in valueData.table property
Table = 'table',
}Get UniversalTrackerValue
Retrieve a single universal tracker value by id.
GET universal-tracker-values/:utrvId
Request
curl --location 'https://api.sg.g17.eco/v1/universal-tracker-values/62d9530de3e05eca98c84b49' \
--header 'Authorization: Bearer TOKEN_HERE'Response
{
"success": true,
"data": {
"_id": "62d9530de3e05eca98c84b49",
"period": "yearly",
"evidenceRequired": false,
"verificationRequired": false,
"status": "verified",
"effectiveDate": "2022-07-21T13:22:20.575Z",
"universalTrackerId": "607818272c2c251ef832bec9",
"initiativeId": "62d9530ce3e05eca98c8465d",
"valueData": {},
"value": 500,
"valueType": "number",
"universalTracker": {
"_id": "607818272c2c251ef832bec9",
"name": "Volunteering Hours - Total",
"valueLabel": "Total number of volunteering hours?",
"instructions": "Please include all volunteering activities by employees during business hours.",
"type": "kpi",
"typeCode": "",
"valueType": "number",
"unit": "h",
"unitType": "time"
}
}
}Get UniversalTrackerValue History
Retrieve the complete history of changes for a universal tracker value.
GET /v1/universal-tracker-values/:utrvId/history
The history endpoint returns all historical changes made to a UTRV, sorted by date (most recent first). Each history entry includes the action type, timestamp, value at that point, and any associated notes or evidence.
Response structure:
interface HistoryResponse {
universalTracker: {
_id: string;
name: string;
valueLabel: string;
type: string;
valueType: UtrValueType;
unit?: string;
unitType?: string;
numberScale?: string;
instructions?: string;
};
history: {
_id: string;
action: 'created' | 'updated' | 'verified' | 'rejected';
date: string; // ISO 8601 timestamp
userId: string; // Resolve user details from users array
// Value fields (for number/percentage types)
value?: number;
unit?: string;
numberScale?: string;
// Complex value data (for text/table/list types)
valueData?: {
data?: string | string[] | Record<string, string | number>;
table?: { code: string; value: string | number }[][];
notApplicableType?: 'na' | 'nr';
};
valueType?: UtrValueType;
note?: string;
assuranceStatus?: 'created' | 'completed' | 'completed_open' | 'rejected' | 'restated' | 'partial';
// Evidence references - resolve full details from documents array
evidenceData?: {
documentId: string;
description?: string;
}[];
}[];
// Lookup arrays to resolve IDs from history entries
users: {
_id: string;
firstName?: string;
surname?: string;
}[];
documents: {
_id: string;
type: 'link' | 'file';
url: string; // For links: the actual URL, for files: signed download URL (~1 hour expiry)
name?: string;
description?: string;
}[];
}Response Structure: The response is optimized to avoid data repetition by separating users and documents into lookup arrays:
history[].userId→ Resolve user details fromusers[]array by matching_idhistory[].evidenceData[].documentId→ Resolve full document details fromdocuments[]array by matching_id
Important Notes:
- The
evidenceDatafield includes a document ID and optional description. - Document URLs have different meanings:
- Link documents: User-provided URL (not validated)
- File documents: Signed download URL with temporary access (~1 hour expiry)
Use Cases:
- Audit trail for data changes
- Tracking data revisions over time
- Understanding data verification workflow
- Compliance and assurance reporting
- Resolving who made changes (via userId → users lookup)
- Accessing evidence documents (via evidence IDs → documents lookup)
Request
curl --location 'https://api.sg.g17.eco/v1/universal-tracker-values/62d9530de3e05eca98c84b49/history' \
--header 'Authorization: Bearer TOKEN_HERE'Response
{
"success": true,
"data": {
"universalTracker": {
"_id": "607818272c2c251ef832bec9",
"name": "Volunteering Hours - Total",
"valueLabel": "Total number of volunteering hours?",
"type": "kpi",
"valueType": "number",
"unit": "h",
"unitType": "time"
},
"history": [
{
"_id": "674d123456789abc12345678",
"action": "verified",
"date": "2024-11-03T10:30:00.000Z",
"userId": "507f1f77bcf86cd799439011",
"value": 500,
"unit": "h",
"numberScale": "single",
"valueType": "number",
"note": "Verified by manager",
"assuranceStatus": "completed"
},
{
"_id": "674d123456789abc12345677",
"action": "updated",
"date": "2024-11-02T14:20:00.000Z",
"userId": "507f1f77bcf86cd799439011",
"value": 500,
"unit": "h",
"numberScale": "single",
"valueType": "number",
"note": "Updated with Q4 data",
"evidenceData": [
{
"documentId": "62abc123def456789012345",
"description": "Q4 volunteering report"
}
]
},
{
"_id": "674d123456789abc12345676",
"action": "created",
"date": "2024-11-01T09:00:00.000Z",
"userId": "507f1f77bcf86cd799439011",
"valueType": "number"
}
],
"users": [
{
"_id": "507f1f77bcf86cd799439011",
"firstName": "John",
"surname": "Smith"
}
],
"documents": [
{
"_id": "62abc123def456789012345",
"type": "file",
"name": "Q4_volunteering_report.pdf",
"description": "Q4 volunteering report"
}
]
}
}Update UniversalTrackerValue
Update a single universal tracker value by id.
Input data is expected to be provided in the default universal tracker unit. Unit conversion is not supported at the moment.
PATCH universal-tracker-values/:utrvId
Single value update
Request
curl --location --request PATCH 'https://api.sg.g17.eco/v1/universal-tracker-values/6364c32a70a4d65de2b83906/update' \
--header 'Authorization: Bearer TOKEN_HERE' \
--form 'value="67"'Endpoint must use 'Content-Type': 'application/x-www-form-urlencoded' for file uploads
Response
{
"success": true,
"data": {
"_id": "6364c32a70a4d65de2b83906",
"value": 67,
"valueData": {},
"status": "verified",
"valueType": "number",
"effectiveDate": "2023-02-28T23:59:59.999Z",
"initiativeId": "62d9218bb3bfaa00089ea678",
"universalTrackerId": "603376a6a9530404ce748936",
"verificationRequired": false,
"evidenceRequired": false
}
}Single value update with evidence links
It's also possible to add evidence links.
Request
curl --location --request PATCH 'https://api.sg.g17.eco/v1/universal-tracker-values/62d9530de3e05eca98c84b49/update' \
--header 'Authorization: Bearer TOKEN_HERE' \
--form 'value="67"' \
--form 'evidenceLinks[0][type]="link"' \
--form 'evidenceLinks[0][link]="www.google.com"' \
--form 'evidenceLinks[0][public]="false"'Response
{
"success": true,
"data": {
"_id": "62d9530de3e05eca98c84b49",
"value": 67,
"valueData": {},
"status": "verified",
"valueType": "number",
"effectiveDate": "2022-07-21T13:22:20.575Z",
"initiativeId": "62d9530ce3e05eca98c8465d",
"universalTrackerId": "607818272c2c251ef832bec9",
"verificationRequired": false,
"evidenceRequired": false
}
}