Skip to content

API packages

Needs review

Needs review: Admin screen mapping per package was derived from admin/config/routes.ts and admin services by name; confirm the less obvious ones (bulk-notifications, assign-without-account, cmi5, adapt).

The API is a Laravel application whose domain code lives in the directories under api/packages. Most were imported from EscolaLMS (escolalms/* composer packages) and are now plain source owned by this repository; a few were written for ulams (adapt, demo, h5p, liascript, lti, tenancy, uploads), and two are vendored third-party forks (laravel-scorm, shopping-cart). Namespaces are Ulams\<Name>\ except for the forks and przelewy24-php.

Every package has a generated reference page (routes, permissions, settings, events, commands, schedules) linked from its heading below. Cross-package lists are in the reference section: permissions, settings, endpoints, events and notifications, artisan commands and scheduled jobs.

Packages are not composer packages and are not auto-discovered. Each one is wired in three places (api/packages/README.md):

  1. PSR-4 entries in api/composer.json (runtime, factories and seeders in autoload, tests in autoload-dev).
  2. Its service provider in api/config/app.php under “Package Service Providers”.
  3. A test suite in api/phpunit.xml (vendor/bin/phpunit --testsuite <name>).

Each package keeps the upstream layout: src/ (with routes.php, config.php, models, services, repositories, policies, events), database/ (migrations, seeders, factories), resources/, tests/, and usually a README.md and an ADMIN.md describing its admin screens.

Create api/packages/<name>/src with a Ulams\<Name>\Ulams<Name>ServiceProvider, add the three entries above, run composer dump-autoload, and seed its permissions from a seeder in the package. New endpoints need a tenant isolation test (Tenancy). The step-by-step guide is Adding an endpoint.

The course model and everything inside it: Course, Lesson (nested lessons), Topic and TopicResource, authors and groups (CourseAuthorPivot, CourseGroupPivot), learner progress (CourseProgress, UserTopicTime, H5PUserProgress, CourseUserAttendance). Public and learner routes under /api/courses (catalogue, program, preview topics, progress, ping), admin routes under /api/admin. Schedules check deadlines hourly and activate courses daily. Used by creators and admins in the admin course editor (/courses/list) and by every learner frontend. Topic content classes are registered by the topic type packages below.

Progress endpoints (GET and PATCH /api/courses/progress/{course}, PUT .../{topic}/ping, POST .../{topic}/h5p) apply the attend policy: a user who is not enrolled (directly or through a group, with an unexpired end date), not allowed to edit the course and not looking at a public course gets 403, a guest 401 and an unknown id 404. PATCH also refuses topics that belong to another course. The demo student is enrolled in every published demo course, so demo pings keep working.

Exports a course as a zip in the .ulam format (content.json plus assets), imports such a zip and clones courses. Admin-only routes under /api/admin; zip imports go through the upload guard. Used from the course list in the admin.

Hierarchical Category tree attached to courses and other content; public /api/categories, admin /api/admin/categories. Admin screen /courses/categories.

Free-form Tag records on any model (courses, webinars, events). Public /api/tags, admin /api/admin/tags. No screen of its own; tags are edited in the forms of the tagged entities.

Static pages (Page) such as terms or “about”, read by learner frontends at /api/pages. Admin screen /other/pages.

Surveys attached to models (courses, webinars and others): Questionnaire, Question, QuestionAnswer, QuestionnaireModel, QuestionnaireModelType. Learners answer through /api/questionnaire; admins build them and read reports under /api/admin. Admin screen /other/questionnaire.

Glossaries: Dictionary, DictionaryWord, word categories and per-user access. Public /api/dictionaries/{slug}/words, admin /api/admin/dictionaries and /api/admin/dictionary-words. Admin screen /other/dictionary.

Learner bookmarks and notes in one Bookmark model (a note is a bookmark with a value), on topics and other models. Learner routes /api/bookmarks, admin /api/admin/bookmarks. No dedicated admin screen.

Converts video topics to HLS with ffmpeg (pbmedia/laravel-ffmpeg). When a topic changes, a ProccessVideo job runs on the long-job queue; bitrates are configured in the package config. Registers its own Video topic content class. Admin status routes under /api/admin/video. The reference frontend plays the result with hls.js.

A topic’s content is a polymorphic “topicable” class registered with the courses package. The generated page lists every registered class; creators see them in Course builder.

The base content classes: RichText (Markdown), Audio, Video, Image, PDF, OEmbed, H5P, ScormSco and Cmi5Au. Also marks SCORM topics complete when the SCO reports completed or passed (ScormScoCompleted). No routes of its own.

Quizzes in Moodle’s GIFT format (GiftQuiz, GiftQuestion, QuizAttempt, AttemptAnswer): multiple choice (one or many right answers), true/false, short answer, matching, numerical, essay (graded by the tutor) and description items, with attempt and time limits. Learner routes for attempts and answers (/api/quiz-attempts, /api/quiz-answers), admin routes for questions and attempts. Admin screen /courses/quiz-reports; questions are edited in the course editor (the admin parses GIFT with @ulams/gift-pegjs).

The Layout topic (LayoutTopic, ADR 0052): a document of approved learner components plus a Markdown fallback. The document is validated against resources/learner-layout-manifest.json, a copy of front/ui/catalogue/learner-layout-manifest.json that yarn workspace @ulams/ui learner-manifest keeps in sync (the UI tests and a package test fail when it is stale). No routes of its own: topics are created through the topic API. See Layouts.

Project assignments: learners upload solution files (Project, ProjectSolution); admins list, download and delete solutions (/api/admin/topic-project-solutions).

Laravel side of the H5P service (api/h5p), written for ulams; it replaced escolalms/headless-h5p. Reads the service’s h5p.contents table read-only (H5PContent), exposes GET /api/admin/h5p/contents and DELETE /api/admin/h5p/unused, and calls the service with H5PServiceClientContract (X-Internal-Token). Admin screens /courses/h5ps and /courses/h5ps/libraries (see H5P libraries).

SCORM 1.2 and 2004 packages: upload and parse (through the upload guard), list, preview and tracking. Learner launch (POST /api/scorm/launch/{sco}) returns a player URL on the tenant’s content origin with a scoped tracking token; tracking writes go through ScormTrackService. Uploads labelled source_format = adapt are Adapt exports. Admin screen /courses/scorms.

Vendored fork of devianl2/laravel-scorm 4.0.1 (namespace Peopleaps\Scorm\, MIT): the manifest parser, entities and the scorm, scorm_sco, scorm_sco_tracking models used by scorm. Kept because no upstream release accepts Carbon 3. Library only; developers touch it when SCORM parsing changes.

cmi5 courses (Cmi5, Cmi5Au): admin upload, list and delete at /api/admin/cmi5, learner player data at /api/cmi5/player/{auId}. Statements go to the lrs package. Each assignable unit becomes a Cmi5Au topic. No dedicated admin screen was found in admin/config/routes.ts.

A small first-party xAPI learning record store for cmi5 content (Statement, State, ActivityProfile, AgentProfile, Client, Access and others), the cmi5 launch endpoints and an admin statement list. xAPI endpoints are under trax/api/{source}/xapi/std. A seeder creates the store owner, client and access.

Courses written in LiaScript Markdown, written for ulams. Every edit, upload or restore adds an immutable LiaScriptVersion of a LiaScriptDocument; assets from zip uploads live in the tenant bucket. Registers the LiaScriptTopic content class; the player runs on the content origin. Admin API /api/admin/liascript, admin screen /courses/liascript.

Adapt Learning course sources as versioned JSON (AdaptSource, AdaptSourceVersion) built into SCORM by an isolated GPL-3.0 worker (ADR 0013, Proposed). Off by default: ADAPT_SOURCE_ENABLED=true turns on /api/admin/adapt (permission adapt_manage, 404 otherwise). The worker itself is not built yet, so builds cannot run outside tests. No admin screen.

LTI 1.3 in both directions (ADR 0012), written for ulams. Platform side: launch external tools from lessons through the LtiLink topic type, receive grades (AGS 2.0) and deep links. Tool side: Moodle, Canvas and others launch ulams courses, with grade passback and a course picker; launch validation uses packbackbooks/lti-1p3-tool. Models include LtiTool, LtiPlatform, LtiKey, LtiLaunch, LtiLineItem, LtiScore. Per-tenant key sets are rotated monthly. Admin screen /integrations/lti (LTI).

Registration, login, password reset, e-mail verification, social login (Socialite), profile, users, groups (Group, GroupUser), user settings and impersonation. Issues Passport personal access tokens; see Authentication. Admin screens /users/list and /users/groups.

REST API over spatie/laravel-permission for roles and their permissions (/api/admin/roles). Admin screen /users/roles. Permissions themselves are seeded by each package; the full list is in Permissions.

Grants course access to users and groups, and lets learners send access enquiries (CourseAccessEnquiry) that admins approve or reject. Admin screen /courses/access.

Assigns e-mail addresses that have no account yet to products and other models (UserSubmission, admin /api/admin/user-submissions); the user gets access after registering. Needs e-mail templates for its events. Used from the admin product, course and webinar forms.

Exports and imports users (and group members) as CSV through /api/admin/csv, using the auth package’s user repository and resources.

Personal and assigned tasks with notes (Task, TaskNote), with completion requests and a scheduled reminder for overdue tasks. Learner and admin routes; admin screen /other/tasks.

Products and what they sell (Product, ProductProductable), carts, orders (Order, OrderItem) and product ownership (ProductUser). Learner routes /api/cart, /api/products, /api/orders; admin routes under /api/admin. Depends on payments and registers shopping-cart. Admin screens /sales/products and /sales/orders.

The CommerceProvider interface (syncProduct, createCheckout, handleOrderEvent) and the WellmsCartProvider adapter that creates cart products for courses through the cart services, with the mapping in commerce_product_links. Used by the Course Builder to price a course; no routes. A Sylius adapter is planned (Phase 6.4).

Vendored fork of treestoneit/shopping-cart 1.6.1 (namespace Treestoneit\ShoppingCart\, MIT): database-backed cart models, CartManager and the carts/cart_items migrations. Library only, used by cart and vouchers; its provider is registered by the cart package, not config/app.php.

Payments (Payment) and gateway drivers: Stripe (through league/omnipay and omnipay/stripe) and Przelewy24. Gateway keys can be changed through Settings. Webhook and admin routes; admin screen /sales/payments.

Vendored PHP client for the Przelewy24 API (namespace Przelewy24\). Library only, no service provider; used by the Przelewy24 driver in payments.

Coupons (Coupon with category, product and user restrictions) applied to a cart before ordering, with configurable discount rules. Extends cart and cannot be used alone. Admin screen /sales/vouchers.

Renders a PDF invoice for an order at GET /api/order-invoices/{id} with barryvdh/laravel-dompdf. The invoice model is in the package (no database table). Learners download it from their orders.

Live webinars (Webinar, participants), with a YouTube livestream and a Jitsi room. Public and learner routes /api/webinars, admin /api/admin. Admin screen /courses/webinars.

Creates YouTube livestreams for webinars through the YouTube Data API (google/apiclient). Admins generate a Google OAuth URL (/api/admin/g-token/generate); the callback stores the refresh token. No models.

A facade that generates Jitsi player parameters and a room URL, with a JWT when an app id and secret are configured; host and keys come from config or Settings. Used by consultations and webinar. No routes or models.

Pencil Spaces integration: creates API users (PencilSpaceAccount) and spaces and returns a login link for the current user.

One-to-one consultations with tutors: Consultation, proposed terms, booked terms and reminders (scheduled jobs one hour and one day before). Learner routes /api/consultations, admin /api/admin. Admin screen /other/consultations.

Enquiries for free consultation access that admins accept (with a meeting link) or reject (ConsultationAccessEnquiry, proposed terms). Admin screen /other/consultation-access.

In-person events (StationaryEvent) with authors, participants, place, programme and capacity. Public /api/stationary-events, admin /api/admin/stationary-events. Admin screen /other/stationary-events.

Logs events emitted by the packages as database notifications (DatabaseNotification) and lets users list and mark them read (/api/notifications); admins list all of them (/api/admin/notifications). Admin screen /analytics/notifications.

Push notifications to many users at once (BulkNotification, sections, recipients) through a push channel on Firebase (kreait/laravel-firebase); learner apps register device tokens at /api/notifications/tokens. Admin API /api/admin/bulk-notifications, used by the admin’s bulk notification pages under Users.

Stores editable templates per channel and event (Template, TemplateSection, Templatable) and renders them when the event fires, replacing the variables registered for that pair. Admin screens /configuration/templates and /users/notifications.

The e-mail channel for templates, with MJML layouts. MJML is compiled through an MJML API when MJML_API_URL is set. Registers the default e-mail templates for user-related events.

The SMS channel for templates, sending through Twilio (TWILIO_* variables, tzsk/sms).

PDF templates (certificates and others) generated when an event fires. Templates are pdfme JSON designed in the admin designer and rendered by the api/pdf service (FabricPDF holds generated PDFs). Learner routes /api/pdfs, admin /api/admin/pdfs.

Adds users to MailerLite groups when events fire (for example registration and paid orders; group names are configurable). Enabled and configured through config or Settings; no routes.

Mattermost integration: listens to account, course and webinar events and creates, blocks or removes Mattermost users and adds them to course and webinar channels (tutors and trainers as channel admins). Uses our own MattermostManager over gnello/php-mattermost-driver. Learner routes under /api/mattermost (own account, credentials, password reset).

Base classes every package uses: BaseRepository with criteria, base API controller and response envelope, the base User model and roles (student, tutor, admin), seeders, test helpers. Routes: GET /api/core/packages (versions from api/packages/versions.json) and /api/core/health-check.

Registers config keys that admins can change at runtime (Config, Setting), and serves public values to frontends (GET /api/settings, GET /api/config). Admin screen /configuration/settings. Every administrable key is listed in Settings.

Database translations (LanguageLine, spatie/laravel-translation-loader) for the API and the frontends. Public /api/translations, admin /api/admin/translations. Admin screens /configuration/translations and /configuration/admin_translations.

Adds extra typed fields (boolean, number, varchar, text, json) to any model, with metadata describing visibility and validation (Field, Metadata). Mostly used for user profile fields. Admin screen /users/fields.

Provisions and removes tenants (Tenant registry in the platform database) and rejects unknown hosts. Written for ulams. Commands ulams:tenant:create|list|delete|sync-env. See Tenancy and Tenants.

Turns a tenant into a public demo: password-less POST /api/demo/login as the seeded student or admin, GET /api/demo, and an hourly reset. Off unless DEMO_MODE=true in the tenant env file. See Demo mode.

Statistics and reports about other components (Report, Measurement): registered metrics whose values a scheduled job stores per day, and report and stats endpoints under /api/admin. Admin screen /analytics/reports.

Resizes images on request (GET /api/images/img with the source path and size parameters), caches the result (ImageCache) and optimises it with spatie/image-optimizer. Used by every frontend for thumbnails.

File manager: upload, list, move and delete files on the tenant disk, with per-user directory access (access_to_directories on users). Admin API /api/admin/file, admin screen /configuration/files.

One upload guard for every path that accepts third-party files (SCORM, cmi5, course import, LiaScript, Adapt): size, extension, content-sniffed MIME type, optional ClamAV scan (UPLOADS_SCANNER=clamd) and a zip inspector (zip-slip, symlinks, zip bombs). Also serves package files to the content origin (GET /api/content/..., ContentFileController). Written for ulams; no admin screen.