Skip to main content

Scholiq — API Reference

Scholiq exposes two categories of API surface:

  1. OpenRegister object API — all CRUD and lifecycle operations on the 9 schemas go through OR's REST API. Scholiq does not wrap these with its own controllers.
  2. Scholiq-specific endpoints — thin PHP controllers for operations OR cannot yet express declaratively: public credential verification, audit-pack ZIP export, admin key management, and health diagnostics.

Base URL (local dev): http://localhost:8080/index.php/apps


OpenRegister object API

Scholiq uses the standard OR objects API. The register slug is scholiq.

List objects

GET /openregister/api/objects?register=scholiq&schema={schema-slug}

Example — list all published courses:

GET /openregister/api/objects?register=scholiq&schema=course&lifecycle=published

Example — list mandatory enrolments for a learner:

GET /openregister/api/objects?register=scholiq&schema=enrolment&learnerId=alice&mandatory=true

Response: standard OR paginated JSON list.

Get single object

GET /openregister/api/objects/{uuid}

Create object

POST /openregister/api/objects
Content-Type: application/json

{
"register": "scholiq",
"schema": "course",
"object": {
"code": "NIS2-2026",
"name": "NIS2 Awareness Training",
"level": "corporate",
"language": "nl",
"mandatoryTraining": true,
"regulationSlug": "NIS2",
"tenant_id": "{tenant-uuid}"
}
}

Update object

PUT /openregister/api/objects/{uuid}
Content-Type: application/json

Lifecycle transition

POST /openregister/api/objects/{uuid}/transition
Content-Type: application/json

{
"transition": "publish"
}

Example — publish a course:

POST /openregister/api/objects/{course-uuid}/transition
{ "transition": "publish" }

If the CoursePublishGuard check fails (no published lessons), the response is 422 Unprocessable Entity with an error message.

Example — sign an attestation:

POST /openregister/api/objects/{attestation-uuid}/transition
{ "transition": "sign" }

AttestationSigningGuard validates the xAPI completion record and sets signature and signingKeyId on the object.

Import register configuration

Used on initial setup (see openregister#1487 workaround):

POST /openregister/api/configurations/import
Content-Type: application/json

(body: contents of lib/Settings/scholiq_register.json)

Scholiq-specific endpoints

All endpoints below require an authenticated Nextcloud session unless marked @PublicPage.

GET /scholiq/api/credentials/{id}/verify

Public (no auth required).

Verifies a credential by ID. Returns validity status and the Open Badges 3.0 payload. Writes a credential.verified audit entry via OR.

Response 200 — valid credential:

{
"valid": true,
"credential": {
"id": "{uuid}",
"learnerId": "{opaque-uuid}",
"kind": "certificate",
"issuedAt": "2026-01-15T10:00:00Z",
"expiresAt": "2027-01-15T10:00:00Z",
"expiryStatus": "valid",
"lifecycle": "issued",
"isOpenBadgesV3Signed": true,
"openbadges3Payload": { ... }
}
}

Response 200 — revoked credential:

{
"valid": false,
"credential": {
"id": "{uuid}",
"lifecycle": "revoked",
"revocationReason": "Employee offboarded"
}
}

Response 404: Credential not found.


GET /scholiq/api/admin/health

Auth required. Admin-only.

Returns observability data for the AdminHealth dashboard widget.

Response 200:

{
"openregisterConnected": true,
"schemaCount": 9,
"auditEventsLast24h": 142,
"mydashInstalled": false,
"lastAuditPackExport": "2026-05-10T08:30:00Z"
}

POST /scholiq/api/compliance/export

Auth required. Compliance-officer or admin role.

Streams an audit-pack ZIP for a given regulation and date range. The export itself is recorded in the OR audit trail.

Request:

POST /scholiq/api/compliance/export
Content-Type: application/json

{
"regulationSlug": "NIS2",
"dateFrom": "2026-01-01",
"dateTo": "2026-05-12"
}

Response: 200 OK with Content-Type: application/zip streaming a ZIP file containing:

FileContents
audit-trail.ndjsonOR audit-trail entries for the regulation and period, one JSON object per line
audit-trail.csvSame entries in CSV format
manifest.jsonExport metadata: regulation, date range, export timestamp, record counts
signature-verification.txtInstructions for offline HMAC/RS256 signature verification

GET /scholiq/api/admin/keys

Auth required. Admin-only.

Lists signing key metadata (key ID, created at, algorithm). Does not expose private key material.

Response 200:

{
"keys": [
{
"id": "tenant-key-v1",
"algorithm": "RS256",
"createdAt": "2026-01-01T00:00:00Z",
"active": true
}
]
}

POST /scholiq/api/admin/keys/generate

Auth required. Admin-only.

Generates a new RSA key pair and stores it via ICrypto. Equivalent to occ scholiq:keys:generate.

Request: No body required.

Response 200:

{
"keyId": "tenant-key-v2",
"algorithm": "RS256",
"createdAt": "2026-05-12T09:00:00Z"
}

GET/POST /scholiq/api/settings

Auth required.

User and admin settings endpoints backed by SettingsController.

GET /scholiq/api/settings — returns current user's Scholiq preferences. POST /scholiq/api/settings — updates preferences.

User preference keys:

KeyTypeDefaultDescription
notify_assignmentsbooleantrueReceive enrolment activation/completion notifications
notify_due_datesbooleantrueReceive T-30/T-7/T-1 due-date reminders
default_viewstringlearnerLanding page after login

Newman collection

A Postman / Newman collection for the scholiq API is in development. See openspec/changes/nextcloud-app/ for the collection scaffold. To run:

newman run openspec/changes/nextcloud-app/scholiq-api.postman_collection.json \
--env-var "baseUrl=http://localhost:8080" \
--env-var "ncUser=admin" \
--env-var "ncPassword=admin"