External LRS — export xAPI statements
Who this guide is for: Tenant administrators who keep learning records in their own Learning Record Store (LRS) — Watershed, Learning Locker, Veracity, SCORM Cloud’s LRS, Yet Analytics or any xAPI 1.0.3 conformant LRS — and want EmbayLMS activity to flow into it automatically.
Overview
Once an LRS is connected, EmbayLMS sends an xAPI statement to it every time something worth recording happens. Nothing is sent before you connect one, and nothing is sent after you disconnect.
| What happens in EmbayLMS | Statement sent | Verb |
|---|---|---|
| A learner completes a module — SCORM, AICC, video, document, web page, download, attendance, self-marked | Module completed, with the SCORM / AICC score and pass/fail when the package reported one | completed |
| A learner completes a quiz module | Module completed, with the passing attempt’s score | completed |
| A cmi5 module’s move-on criteria are met | Module satisfied (the LMS-issued cmi5 statement) | satisfied |
| A quiz attempt is graded (pass or fail; essays once the instructor finishes grading) | The attempt, with raw / max / scaled score | passed / failed |
| A learner completes a course | Course completed | completed |
A cmi5 unit (AU) sends any statement, and the LMS launched statement | Forwarded as-is (see Identity below) | as sent |
Every statement carries the module or course as its object
(https://{your-portal}/xapi/activities/module/{id}), the course as its parent
context activity, the enrollment as context.registration, and
context.platform: "EmbayLMS".
Delivery and retries
Statements are sent in the background, usually within seconds. Each one is sent
with PUT /statements?statementId=… using an ID that is fixed for the event it
describes, so a retry can never create a duplicate in your LRS.
- A network error, a timeout, or an LRS error (
5xx,408,429) is retried 5 times with growing delays (30 s, 1 min, 2 min, 4 min). - A refusal that retrying cannot fix — wrong credentials (
401/403), a statement the LRS rejects (400), an ID conflict (409) — stops at once. - Either way the statement stays in the Delivery log as Failed, with the reason, and you can retry it (or all failed statements) after fixing the cause.
Prerequisites
- The Owner role, or a custom role holding
integration.lrs:manage(integration.lrs:viewshows the page and the log read-only). - Your LRS’s xAPI endpoint and a Basic-auth key/secret pair with permission to write statements. A write-only key is enough.
- The endpoint must be a public
https://address. Internal addresses (localhost, private networks, cloud metadata addresses,.internal/.localnames) are refused, and redirects are never followed.
Step 1 — Create credentials in your LRS
In your LRS, create a client / key pair for EmbayLMS with statement write
access. Note the endpoint it shows — usually something like
https://lrs.example.com/data/xAPI/ (it ends before /statements).
Step 2 — Connect the LRS
- Go to Settings → Integrations → External LRS.
- Enter the LRS endpoint, the Username or key and the Password or secret.
- Choose How learners are identified (see Identity below). Keep Anonymous ID unless your LRS must match learners by email.
- Click Connect LRS.
The secret is encrypted as soon as it is saved and is never shown again: the page shows a masked username and “Saved (hidden)”. To change either, type the new value; leave a field blank to keep what is saved.
Step 3 — Test the connection
Click Test connection. EmbayLMS makes one read-only request
(GET /statements?limit=1) with your credentials — nothing is written to your
LRS — and shows the result:
| Result | Meaning |
|---|---|
| Connected | The LRS accepted the credentials. |
| Connected — write-only | The key can write but not read. That is all the export needs. |
| Refused the username or password | Wrong key or secret — edit the connection. |
| No xAPI endpoint found | The address is not the xAPI base URL — check the path. |
| Not allowed | The address is not a public https:// address. |
| Did not answer / could not be reached | Check the address and that the LRS is up. |
Step 4 — Watch the delivery log
The Delivery log lists every statement sent in the last 90 days: status (Delivered, Pending, Failed), what it records, the LRS’s HTTP answer, the number of attempts and, for failures, the reason. View statement shows the exact JSON sent. Retry re-sends a failed statement with the same ID; Retry all failed re-sends up to 500 at a time — use it after fixing credentials.
Identity — how learners appear in your LRS
| Setting | Actor sent | Personal information shared |
|---|---|---|
| Anonymous ID (default, recommended) | {"account": {"homePage": "https://{your-portal}", "name": "{EmbayLMS user ID}"}} | None. The ID is an opaque identifier you can match to a person in Users or through the REST API. |
| Email address | {"mbox": "mailto:{learner email}"} | The learner’s email address. |
The Anonymous ID is the default because it lets your LRS track each learner consistently without EmbayLMS disclosing names or emails to another system. Choose Email address only when your LRS must match learners by email and your organization has a basis to share it (Québec Law 25, PIPEDA): you remain the controller of the data in your LRS. A learner with no usable email (for example an account anonymized under the retention policy) is always sent with the Anonymous ID. Names are never sent in either mode, and statements forwarded from cmi5 units have their actor replaced by the one above.
Configuration reference
| Field | Required | Notes |
|---|---|---|
| LRS endpoint | Yes | xAPI base URL, public https:// only. /statements is appended. |
| Username or key | On first save | Basic-auth username. Shown masked after saving. |
| Password or secret | On first save | Basic-auth password, encrypted at rest (AES-256-GCM). Never shown again. |
| How learners are identified | Yes | Anonymous ID (default) or Email address. |
| xAPI version | — | Always 1.0.3 (X-Experience-API-Version header). |
Disconnecting
Disconnect stops the export immediately and deletes the saved credentials. The delivery log stays until its 90-day retention ends. Statements already in your LRS are not touched.
Data retention
Delivery-log rows are kept 90 days and then deleted automatically, whatever their status. They are also deleted with a learner when the learner’s account is erased. Your LRS is the system of record for statements it has received.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| This address is not allowed when saving | The endpoint is http://, an IP in a private range, or an internal host name. Use the LRS’s public https:// address. |
| Test says refused the username or password | Re-enter the key and secret — many LRSs show the secret only once when the key is created. |
| Test says redirect | The LRS answered with a redirect (often http → https, or a missing trailing path). Enter the final address. |
| Statements show Failed — conflict | The LRS already holds a different statement with that ID — usually because the same LRS also receives statements from another system using the same IDs. Contact support. |
| Statements show Failed — no saved secret | The connection was created without a secret or the secret could not be read. Edit the connection, enter the secret, then Retry all failed. |
| Nothing appears in the log | No learner activity has completed since the LRS was connected — earlier activity is not back-filled. |
| Statements stay Pending | Deliveries are being retried after an LRS error; the reason is shown on the row. |