External API
The External API uses personal API keys for two jobs. The team reporting permissions (team:*, Org Manager only) give your organization read-only access to its Rogue Arena training records, so you can feed an LMS, data warehouse, compliance dashboard, or your own reporting workflow without recreating the Team Hub UI. The deployment permissions (deployments:*) deploy and control labs. See the Deployments API.
The team reporting endpoints return data only. Your integration decides how often to call them, which users or event types to request, and how to present or retain the results.
Create a key
Section titled “Create a key”- Sign in to Rogue Arena and open Team Hub.
- Select External API in the left sidebar.
- Give the key a name that identifies the integration, such as
Learning data warehouse. - Select only the permissions that integration needs.
- Choose an expiration date, no more than 365 days away, and select Create API key.
- Copy the full key right away. Rogue Arena stores only a one-way hash and can’t show the secret again.
Each person can have up to five active keys. A person’s keys are revoked when they leave the team, lose the API Key Use permission, or have their account disabled, and every key stops authenticating as soon as its organization is disabled or deleted. If the account that created or revoked a key is permanently deleted, that attribution shows as null. The key’s record and the rest of its audit history remain. To rotate a key, create a replacement, update the integration, confirm it works, and then revoke the old key.
Organization and learner scope
Section titled “Organization and learner scope”Every request is authorized against the organization’s current Team Hub roster. A user-specific route accepts a userId only while that account is a current member of the key’s organization. When you remove a learner, they leave that organization’s API scope immediately.
In the current Team Hub data model, training history belongs to the learner’s account and is not frozen in an organization record. The history moves with the account: if the learner later joins another organization, their retained history can appear in that organization’s authorized results. Before you remove a learner, export any records you need to keep, and apply your own retention policy to the exported data.
Authenticate
Section titled “Authenticate”Send the key as an HTTP bearer token. The production base URL is https://arena.roguelabs.io.
curl --fail-with-body \ --header "Authorization: Bearer $ROGUE_ARENA_TEAM_API_KEY" \ "https://arena.roguelabs.io/api/v1/team/users?limit=100"Keys start with ra_training_live_. Never put a key in source control, browser code, a shared document, or a deployed lab VM. Keep it in your platform’s secret manager.
Permissions
Section titled “Permissions”| Permission | Grants access to |
|---|---|
team:members:read | Member names, usernames, email addresses, account status, and stable user IDs |
team:progress:read | Courses, scenarios, curricula, chapter unlocks, question completion, and progress summaries |
team:answers:read | Learner-submitted answers, correctness, score, and submission context |
team:events:read | Training, certification, deployment, chapter, and answer events |
team:activity:read | Sharing, file, snapshot, warp, and daily VM, VPN, keystroke, and video activity |
team:activity:read is a separate permission because this activity is more sensitive. Each event type needs its matching permission, and a key with both permissions can read the whole unified stream.
Endpoints
Section titled “Endpoints”| Endpoint | Purpose | Required permission |
|---|---|---|
GET /api/v1/team/users | Find active or disabled members and obtain stable user IDs | team:members:read |
GET /api/v1/team/training-progress | Fetch compact progress rows across the team | team:progress:read |
GET /api/v1/team/users/{userId}/training-progress | Fetch a member’s detailed course, scenario, curriculum, chapter, and question progress | team:progress:read |
GET /api/v1/team/users/{userId}/answer-attempts | Fetch a member’s answer-attempt history | team:answers:read |
GET /api/v1/team/users/{userId}/deployments | Fetch lifecycle history for deployments launched by that member | team:progress:read |
GET /api/v1/team/events | Fetch the unified, sanitized event stream | team:events:read and/or team:activity:read, according to the requested types |
The downloadable OpenAPI 3.1 document is the canonical source for parameter and response schemas.
To deploy and control labs from your own code, add the deployments:* permissions to a key and see the Deployments API.
Start with a user
Section titled “Start with a user”List users first and save each member’s id. That’s the stable userId the other endpoints accept.
curl --get --fail-with-body \ --header "Authorization: Bearer $ROGUE_ARENA_TEAM_API_KEY" \ --data-urlencode "search=alex@example.com" \ --data-urlencode "status=all" \ "https://arena.roguelabs.io/api/v1/team/users"Then request that user’s detailed training state:
curl --fail-with-body \ --header "Authorization: Bearer $ROGUE_ARENA_TEAM_API_KEY" \ "https://arena.roguelabs.io/api/v1/team/users/USER_ID/training-progress"For high-volume syncs, use the compact team endpoint and follow nextCursor. The detailed endpoint is meant for drilling into one user.
Interpret historical context
Section titled “Interpret historical context”Answer attempts keep the curriculum, scenario, target, and question context from submission time when that snapshot exists. courseId and courseName work differently: they’re nullable and inferred from current data. After course relationships change they can be unavailable or ambiguous, so don’t treat them as a snapshot of the course at submission time.
Answer history includes attempts from earlier progress cycles. A non-null archivedAt means a learner-progress reset archived the attempt, and current progress totals count only active attempts. Keep these records when an audit needs the complete history. Filter them out when you reconcile the history against the current attemptCount and questionsAnswered values.
For new direct submissions, response snapshots include the learner-facing text of the selected multiple-choice options, and safe labels for submitted matching, ordering, and diagram answers. The corresponding IDs are still included. Older snapshots can have empty or null label values, and malformed response snapshots come back as unavailable. These fields hold only what the learner submitted. They never include unselected choices, authored correctness flags, or answer-key configuration.
When team collaboration credits an answer to another learner, that recipient’s row has origin: "collaborative". The attempt, correctness, score, and curriculum context remain available, but response is { "kind": "unavailable" }. This keeps one learner’s submitted content from crossing organization boundaries through a collaborator’s history.
Use context.targetType to tell chapter attempts from ctf_node attempts. Chapter attempts fill in chapterId and chapterName, and CTF attempts fill in ctfNodeId and ctfNodeName. The fields for the other target type are null.
The deployments endpoint reports deployments owned and launched by the selected member. It leaves out deployments the member only accessed as a shared guest. To analyze guest participation, use sharing and activity events. startedAt is the first time the owner or an authorized participant opened the owned deployment.
What is deliberately excluded
Section titled “What is deliberately excluded”The API is scoped to the accounts on the organization’s current roster and returns only reviewed reporting fields. It never returns internal service records, correct-answer keys, uploaded file contents, raw logger JSON, private file paths, window titles, VM identifiers, or voucher identifiers. The learner-owned history behavior described above still applies when an account changes organizations.
Some older answer attempts can’t be matched exactly to the deployment or content version that existed when the learner answered. Those records carry explicit legacy_unavailable markers, and Rogue Arena doesn’t guess the missing values. Deployment history marks its legacy gaps the same way, with historyCoverage: "legacy_partial".
Next: Pagination, rate limits, and errors or the event catalog.