Public API
RTOPilot exposes a small HTTP API for external systems (typically an LMS) to push data into the platform. This is separate from the internal API used by the RTOPilot UI — it lives under the /api path prefix and is authenticated with a per-organisation API key.
Written By Albert
Last updated 22 days ago
Base URL — for production, https://v2.rtopilot.com.au/api
Authentication
All public-API requests must send your organisation's API key as a Bearer token in the Authorization header:
Authorization: Bearer rtop_<your-api-key> API keys are 64-character hex strings prefixed with rtop_. The key identifies the training organisation that issued it; every request is automatically scoped to that organisation's data — there is no separate organisationId field on any endpoint.
A request without a valid Authorization header returns 401 Unauthorized when the header is missing, or when the Bearer value does not match an active API key.
Managing your API key
API-key management lives in the admin portal under Developers → API Settings.
Create API key — generates a new API key for the organisation. Only available when no key exists.
Rotate API key — replaces the existing key with a new one. The old key stops working immediately, so you must update every integration before rotating.
The full key is shown once, on creation or rotation. After that the UI only displays a masked form (rtop_abc1...wxyz); store the full key in your secrets manager when you create it.
A single API key has full access to every public-API endpoint for the issuing organisation. Treat it like a production database password:
Never commit it to source control.
Never embed it in a client-side application or mobile app.
Rotate it immediately if you suspect it has leaked.
Endpoints
PUT /api/enrolments/lms-progress
Update the LMS progress for one or more enrolments matched by their LMS enrolment ID.
This endpoint is the inbound counterpart to the LMS integration: when a student completes work in your LMS, call this endpoint to sync their progress back into RTOPilot. RTOPilot will recalculate marking and certificate status, and email the student if their certificate status changes.
Request:
PUT /api/enrolments/lms-progress Authorization: Bearer rtop_<your-api-key> Content-Type: application/json { "lmsEnrolmentId": "your-lms-enrolment-id", "progress": 75 } Body fields:
lmsEnrolmentId(string, required) — the enrolment ID assigned by your LMS. RTOPilot stores this value when the enrolment is first created in the LMS and uses it to find the matching RTOPilot enrolment(s).progress(number 0-100, required) — the student's overall progress through the course, as a percentage.
Response:
200 OK with an empty body. The response is sent immediately; marking, certificate updates and notification emails are processed asynchronously after the response is returned.
Behaviour notes:
If multiple RTOPilot enrolments share the same
lmsEnrolmentId(for example, after a transfer), all matching enrolments are updated.The endpoint is monotonic: an enrolment is only updated when the new progress is strictly greater than its current
lmsEnrolmentProgress. Submitting a lower or equal value is a no-op (the response is still200). This means the endpoint is safe to call repeatedly with the same payload.Progress is converted into per-unit and per-outcome results by RTOPilot. If the resulting marking pushes the enrolment over a certificate threshold, certificates are updated and a notification email is sent to the student.
Errors
The public API returns standard HTTP status codes. Error responses are JSON in the form:
{ "title": "Bad Request", "message": "lmsEnrolmentId is required" } 400 Bad Request — body failed validation (missing field, wrong type,
progressout of range).401 Unauthorized — missing or invalid API key.
500 Internal Server Error — unexpected error on the RTOPilot side. Safe to retry with backoff.
Code examples
The same examples are available in the admin portal under Developers → API Settings → Public API Endpoints → View Examples, with copy-to-clipboard support and Node.js, Python, C# and cURL variants.
cURL
curl -X PUT 'https://v2.rtopilot.com.au/api/enrolments/lms-progress' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer rtop_YOUR_KEY_HERE' \ -d '{"lmsEnrolmentId":"abc-123","progress":75}' Node.js
const response = await fetch( 'https://v2.rtopilot.com.au/api/enrolments/lms-progress', { method: 'PUT', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.RTOPILOT_API_KEY}`, }, body: JSON.stringify({ lmsEnrolmentId: 'abc-123', progress: 75, }), }, ); if (!response.ok) { throw new Error(`RTOPilot returned ${response.status}`); } Python
import os import requests response = requests.put( 'https://v2.rtopilot.com.au/api/enrolments/lms-progress', headers={ 'Content-Type': 'application/json', 'Authorization': f"Bearer {os.environ['RTOPILOT_API_KEY']}", }, json={'lmsEnrolmentId': 'abc-123', 'progress': 75}, ) response.raise_for_status()