Manifest and Wire Protocol
Reference for the on-disk configuration and the data sent over the network. You do not normally touch either — the editor writes the manifest and the SDK handles transmission — but this is useful for debugging and review.
The manifest
Location: Assets/StreamingAssets/aruvr_manifest.json. Written by the editor when you link a
scene; baked into the build. Do not edit by hand.
Multi-app format (current)
{
"track_url": "https://<track-endpoint>",
"apps": [
{
"scene": "Warehouse_Confined_Space",
"app_id": "3aa41c85-2fb8-4cd7-902d-f644bcaa0510",
"app_name": "Confined Space",
"runtime_token": "s16uocjb",
"program_ids": [5]
},
{
"scene": "FireModule",
"app_id": "e9ce2641-976e-4877-baf2-f56b1a3b21de",
"app_name": "Server Room",
"runtime_token": "a1b2c3d4",
"program_ids": [4]
}
]
}
| Field | Meaning |
|---|---|
track_url |
The endpoint statements are POSTed to (shared across apps in the manifest). |
apps[].scene |
The Unity scene name this app is used in. |
apps[].app_id |
The app’s UUID. |
apps[].app_name |
The app’s display name. |
apps[].runtime_token |
The write-only token that authenticates tracking for this app. |
apps[].program_ids |
The program(s) the app reports into. |
At runtime the tracker uses runtime_token and track_url; the rest is informational.
Legacy single-app format
A flat form is also accepted (one app, no apps[] array):
{
"track_url": "https://<track-endpoint>",
"app_id": "…",
"app_name": "…",
"runtime_token": "…",
"program_ids": [4]
}
The wire protocol
Request body
Statements are POSTed to track_url as JSON:
{
"token": "<runtime_token>",
"learner_id": "SESSION-4821",
"learner_name": "A. Key",
"launch_id": "0f9c…",
"completion": "passed",
"score": 100,
"statements": [ /* … */ ]
}
tokenauthenticates the app (resolves server-side to app/program/organisation).launch_iddiscriminates one attempt from another for the same learner.completionandscoreare included when set; completion is sticky server-side.
Statement shape
{
"id": "b1c2…",
"verb": "scored",
"targetId": "aruvr:dp:<dpGuid>",
"timeStamp": "2026-07-20T10:15:42.123Z",
"description": {
"kind": "track_impact",
"label": "Valve closed in correct sequence",
"competency_id": 11,
"polarity": "positive",
"name": ""
}
}
verb—"scored"(a decision was made) or"experienced"(a decision became available, emitted byArm()).targetId—aruvr:dp:followed by the decision point’s GUID.description.kind—"track_impact"or"assign_score". Forassign_score,nameholds the numeric points and the sign setspolarity.competency_id—0means “no competency” (the program/content default applies).
De-duplication
Every statement has a unique id. Retried or overlapping batches are safe: the server keeps the
last write per id, so a request that fails after the server received it never double-counts.
Batching and cadence
- Batch size: up to 100 statements per request.
- Flush cadence: every 15 seconds, on application pause, and on
SetCompletion/Flush().
The on-disk queue
Statements are buffered to Application.persistentDataPath/aruvr_queue.json and restored on
launch, so a session survives network loss, sleep, and the app being killed.
