Data format
The Reporting API provides a REST style API for access to information stored in reporting collections.
Data is always returned as JSON, and you may add an optional output=pretty argument to pretty-print the output JSON.
Authentication
An API key is used to authenticate as a user of the system, and gives the external system the same permissions as that user. Multiple API keys can be generated for a single application to provide external systems with differing levels of access.
Access to the Reporting API requires that the API user is a member of the Reporting API group.
More on this in the Authentication section below.
Endpoints
Endpoints are relative to the system base URL. For example, if the system URL used by the service is https://app.example.org then given the endpoint /api/example the URL https://app.example.org/api/example should be requested.
The following endpoints are included in the Reporting API:
collectionscollectioncollection-data
Authentication
Before you can do anything, you need an API Key. This acts as your password.
Step A: Get your Key and set permissions
- Log into your application as an Administrator.
- Go to
System Management > Users → SRV - Select user
Reporting API access - Click the New API key link at the end of the page, give it a name, and copy the key immediately (you won't be able to see it again!).
Note: You can add API keys to Active Users as well. If you do this for the purpose of granting access to the Reporting API, you must also add Reporting API to the user’s Group Membership.
Step B: Authenticate with the API
The API uses HTTP Basic Auth:
- Username: The username is always
haplo - Password: The API Key created in Step A
Example Header: If your API key is ABC123XYZ, your authentication header would be the base64 encoded version of haplo:ABC123XYZ.
Tip: If you use a tool like Postman or curl, simply select "Basic Auth", type haplo as the username, and paste your API key as the password. The tool handles the encoding for you.
The Reporting Workflow
The Reporting API works in three logical steps:
-
Discover: Ask "What lists of data (Collections) do you have?"
- Using the
collectionsendpoint
- Using the
-
Inspect: Ask "What columns (Facts) are in this specific list?"
- Using the
collectionendpoint
- Using the
-
Retrieve: Ask "Give me all the rows of data."
- Using the
collection-dataendpoint
- Using the
As for 1 and 2 above, you will see something very similar if you navigate to the Reporting Administration page in the application itself:
STEP 1: Discover Available Collections
Goal: You want to know what data sets are available to you.
- The Endpoint:
GET /api/reporting/v0/collections - Full documentation: https://docs.haplo.org/standard/reporting/rest-api/collections
The Request:
GET https://{your-app}.cayuse.com/api/reporting/v0/collections?output=pretty Authorization: Basic (haplo:YOUR_API_KEY)
The Response (Simplified):
{
"collections": [
{
"name": "absences",
"description": "Absences",
"categories": [],
"info": "/api/reporting/v0/collection/absences",
...
},
{
"name": "academic_enrolment",
"description": "Academic enrolment",
"categories": [
"phd:academic_progress"
],
"info": "/api/reporting/v0/collection/academic_enrolment"
}
]
}Note the info field—it tells you exactly where to go for the next step!
Collections available depend on which applications you are using. E.g. if you are not a GEM customer, you will not see GEM-specific collections, such as absences (which we will be using as an example in the next steps).
Step 2: Inspect a Collection (Facts)
Goal: You chose the "absences" collection and want to know what data columns are inside it before you download everything.
- The Endpoint:
GET /api/reporting/v0/collection/[collection_name] - Full documentation: https://docs.haplo.org/standard/reporting/rest-api/collection
The Request:
GET https://{your-app}.cayuse.com/api/reporting/v0/collection/absences?output=pretty
Authorization: Basic (haplo:YOUR_API_KEY)
The Response (Simplified):
{
"name": "absences",
"status": "ready",
"facts": [
{
"name": "ref",
"type": "ref",
"description": "Reporting object"
},
{
"name": "academicYear",
"type": "ref",
"description": "Academic year"
},
{
"name": "title",
"type": "text",
"description": "Title"
},
{
"name": "researcher",
"type": "ref",
"description": "Doctoral Researcher"
},
{
"name": "project",
"type": "ref",
"description": "Project"
},
{
...
}
],
"data": "/api/reporting/v0/collection-data/absences"
}Status: If this says "ready", the data is up-to-date.
Data: This URL is your link for Step 3.
Step 3: Retrieve the Data
Goal: Download the actual rows of data.
- The Endpoint: Use the endpoint provided in the data field from the previous step.
- Full documentation: https://docs.haplo.org/standard/reporting/rest-api/collection-data
The Request:
GET https://{your-app}.cayuse.com/api/reporting/v0/collection-data/absences?output=pretty
Authorization: Basic (haplo:YOUR_API_KEY)
The Response (Simplified):
{
"name": "absences",
"status": "ready",
"at": "2026-01-19T04:17:31.386Z",
"columns": [
"ref",
"academicYear",
"title",
"researcher",
"reason",
"start",
"end",
...
],
"rows": [
[
"80qw9",
null,
"Suspension - Mr Postgraduate Student",
"80999",
"Personal",
"2025-12-01T00:00:00.000Z",
"2026-03-02T00:00:00.000Z",
...
],
[
...
]
]
}Notice how the response is split into the columns array ([]) and the rows array (the data). This is not very easy to read for a human, but is very suitable for processing programmatically.
Things to note:
You don't need to memorise the URL structure for Steps 2 and 3. Just call Step 1, and the JSON response will give you the URLs for the next steps.
Reporting data is often cached or pre-calculated for performance. Check the status field in Step 2 to ensure the report isn't currently regenerating.