Skip to main content

Turn Results into a usable reporting dataset

Map Result answers to the correct Checklist revision, resolve question and option IDs, and build reliable reporting rows.

Written by Logan Bowlby

Overview

Turn Checklist Results into a reporting dataset with readable questions and answers. Use this guide when your API export contains elements/… or options/… IDs instead of labels, or when historical answers need the correct Checklist version.

At a glance

Who can do this

Integration developers with a read-only API key

Where

/api/customers/results and /api/customers/checklists

Works on

Public API; Backend (web) for setup

Availability

API access, enabled per organization by Mobaro — ask your CSM


Prepare the reporting records

1. Read and retain the Results

Send x-api-key: YOUR_API_KEY from your server. Pulling Results via the API explains authentication and paging. Results allow at most 20 records per page; a larger Limit returns 400. Keep each Result’s id, checklistId, checklistRevision, language, Location and timestamps alongside the original JSON.

GET https://app.mobaro.com/api/customers/results?Limit=20&Offset=0&OrderBy=received
x-api-key: YOUR_API_KEY

For recurring extraction, use Build an incremental Results sync. Completion time is not arrival time: offline work can reach Mobaro later. Apply rate-limit backoff as described in Handling errors, rate limits, and retry logic.

2. Fetch the matching Checklist revision

For each distinct (checklistId, checklistRevision) pair, request the Checklist with includeContent=true and the revision from that Result. Use a URL encoder for the ID and query values. This example uses the ID’s suffix in the route; keep full IDs in your stored data.

GET https://app.mobaro.com/api/customers/checklists/654321-A?includeContent=true&revision=REVISION_FROM_RESULT
x-api-key: YOUR_API_KEY

⚠️ Heads-up: Without includeContent=true, pages is empty. Without the original revision, you can label an old answer with today’s question or options. If the revision cannot be retrieved, flag the row as unresolved; do not silently substitute the current Checklist.

3. Build the question lookup

Walk every pages[].elements[] entry and index questions by id. Also walk each group’s elements: Select Question Groups and Water Quality groups contain child questions. For a Select group, children share the group’s options; retain the parent context.

Question text and option text are language dictionaries. Choose the Result’s language, then the Checklist’s primaryLanguage, then an available translation. Preserve the chosen language. Use element type and stereotype; static content is not an answered question.

4. Map answers without losing detail

Match values[].question to the question lookup. Keep answers as an array and preserve the original strings before any conversion.

Value

How to handle it

Select answers

Match answer IDs to options[].id; use each option’s localized text. Preserve multiple selections.

Numbers and measurements

Use the question type to parse numeric strings. Retain measurementUnit; do not convert every answer to a number.

Text and other question types

Retain the raw answer and type. Add a tested type-specific decoder when needed; do not guess from the string alone.

Comments and evidence

Keep comment, images, assignments and slots separately from the answer.

Missing or unscored values

Keep nulls and empty arrays distinct from zero, false and a failed answer. Use supplied points, maximumPoints and score.

A missing answer alone does not prove that a question failed: Checklist logic and question types affect what is answered. Do not infer compliance or recalculate scores from flattened text.


A worked mapping

Example: an opening inspection. These are reduced, valid JSON fragments with fictional data. The Checklist fragment comes from the Result’s recorded revision.

{
"checklistId": "checklists/654321-A",
"checklistRevision": "example-revision",
"language": "en",
"values": [
{
"question": "elements/1001-A",
"answers": [
"options/2001-A"
]
},
{
"question": "elements/1002-A",
"answers": [
"2.5"
],
"measurementUnit": "bar"
}
]
}
{
"primaryLanguage": "en",
"pages": [
{
"elements": [
{
"id": "elements/1001-A",
"type": "SelectQuestion",
"stereotype": "Question",
"text": {
"en": "Guard secured?"
},
"options": [
{
"id": "options/2001-A",
"text": {
"en": "Yes"
}
}
]
},
{
"id": "elements/1002-A",
"type": "NumberQuestion",
"stereotype": "Question",
"text": {
"en": "Pressure"
},
"measurementUnit": "bar"
}
]
}
]
}

Question ID

Question

Mapped value

elements/1001-A

Guard secured?

Yes

elements/1002-A

Pressure

2.5 bar

In your destination, retain Result ID, Checklist ID, revision and question ID on each row. Keep answers as JSON or use a child table with an answer position. Store evidence in a separate child table to avoid multiplying answer rows.


Check the finished dataset

  • Compare a sample with the same Results in the Backend, including a grouped question, multiple selections and an older Checklist revision.

  • Track unresolved question and option IDs explicitly. Do not discard their raw answers.

  • Upsert Results by their Mobaro ID. Define how a changed Result replaces its existing answer rows.

  • A webhook Results snapshot has no values array. Fetch the Result for answers; handle deletion events without expecting that fetch to succeed.


Best practices

  • Cache Checklist content by both ID and revision.

  • Store UTC timestamps and the supplied language/time-zone context.

  • Keep raw JSON so you can improve a decoder without exporting everything again.


Frequently asked questions

How do I turn elements IDs into question text?

Fetch the Checklist identified by the Result, with includeContent=true and its checklistRevision. Match values[].question to element IDs, including group children.

Why does the Checklist API return an empty pages array?

The Checklist API leaves pages empty unless you request includeContent=true. For historical Results, also send the recorded revision.

Why does an answer contain an options ID?

Select Question answers identify selected options. Match the ID to the original revision’s option list; grouped Select questions use their group’s options.

Can I use a question’s text as the reporting key?

No. Text can change or be translated. Retain the question ID together with Checklist ID and revision; use the text as a display label.

Did this answer your question?