ZAYEED preview
Home / Integrations

Into the VLE without an integration project

Zayeed's server is an LTI 1.3 tool. A teacher places the activity, a student clicks it, and the mark goes back to the gradebook. There is no bespoke connector to commission and no nightly CSV to reconcile.

LTI 1.3

# point the server at a signing key and the platforms it trusts
export ZAYEED_TOOL_URL=https://exams.example.edu   # where the platform reaches the tool
export ZAYEED_APP_URL=https://app.example.edu    # where a launched student lands
export ZAYEED_LTI_KEY=./lti-private.pem         # generated on first use if absent
export ZAYEED_LTI_CONFIG=./lti-platforms.json    # issuer, client id, auth + token URLs

/lti/config describes the tool for a platform administrator and /lti/jwks publishes its public key. The private key never leaves the server, and the gradebook credential never reaches a device.

QTI 3.0

Import and export both run through a dedicated package. Where a construct does not map cleanly in either direction, the item carries a note saying so. Silent loss during an interchange is worse than a refusal, because nobody finds it until the paper has already been sat.

Packs

The .mcq container is the interchange format when there is no network at all: items, media, rules, question sets and the on-screen keyboard layout in one file, encrypted and signed, with a lossless bridge to and from the database. It is specified rather than merely shipped — the specification and its test vectors are published, so a reader can be written from them alone — and every shell still opens the .mcqx ZIP it replaced and the legacy MCQPro banks that came before that, deciding which by reading the bytes.

The same container carries a sync bundle: the changes one device has that another has not seen, rather than a snapshot. Hand it over on a memory stick and it merges into whatever the other machine has done since; apply it twice and the second time changes nothing.

Slides and meetings

Five panels open a live room from the questions you were going to ask anyway: a PowerPoint taskpane, a Google Slides sidebar, a Microsoft Teams tab, a Zoom app and a Webex embedded app. There is no second set of questions to author and nothing to keep in step with the first — the questions go up as text and the relay decides what a question is, so one deck becomes the same questions whichever host it is presented from.

Two of the five read the deck themselves. The three meeting clients cannot: none of Teams, Zoom or Webex will show an app the screen being shared, which is the right design and not an oversight, so those three take the questions as pasted text — through one panel, not three. Three copies of it would be three panels that answered the same question three ways within a term.

A slide becomes a question when it has options under it. Mark the right one with a trailing *, a tick or (correct), or state it in the notes as answer: b. points:, seconds:, rating 1-5, nps, ranking, open and skip are read from the same place. Before anybody is asked anything the panel lists, slide by slide, what it read, what it guessed and what it skipped — and a slide with no key is a poll rather than a defect. A room only runs as a scored quiz when every question it read carries a key, whatever the panel asks for: a leaderboard built from two of nine questions is a leaderboard about two questions.

Two limits belong to the hosts rather than to us, and the panels say so where you would hit them:

All five talk to your relay: the address you give the panel is your institution's server, and the deck, the answers and the names never pass through us. Install steps and the manifests are on the add-ins page. None of the five is published in a vendor store — not the Office store, the Teams catalogue, the Zoom Marketplace or Webex App Hub — so each is created against your own account from the manifest published beside it, which is ten minutes of an administrator’s time and is also what keeps all of this on your server rather than ours.

The API, and provisioning

Everything a person can do through a screen, an institution can do through /v1: 77 documented operations across packs, questions, results, sittings, live-room results, webhooks, proctoring, scheduling, the member directory and the audit log. The OpenAPI document at /v1/openapi.json is not written alongside the server — the router is built from it, and a documented operation with no handler stops the server at startup. That is the only way a published surface stays true: it cannot drift from the code, because it is the code.

# issue a token that can only read results, then use it
curl -X POST https://exams.example.edu/v1/tokens \
  -H 'authorization: Bearer '$SESSION \
  -d '{"name":"results export","scopes":["results:read"]}'
# => {"token":"zy_7f3a_...","shownOnce":true}

curl https://exams.example.edu/v1/results?windowId=win_summer \
  -H 'authorization: Bearer zy_7f3a_...'

Single sign-on

SAML 2.0 and OpenID Connect, because single sign-on is the one thing an institution will not replace to buy an examination system. An identity team pastes one URL — /saml/metadata — into their provider, and the certificate that is allowed to assert who somebody is comes from configuration here. It is never taken from the KeyInfo in the document being checked, because a document that nominates its own verifying key is only asking to be signed by whoever is holding it.

SCIM 2.0

An institution does not want to provision people into Zayeed. It wants to provision them once, into whatever it already runs — Entra, Okta, Google Workspace — and have everything it bought follow. So /scim/v2 speaks Users, Groups and the discovery documents a provider expects, and the connector holds one scope: directory:write.

Who did what, to what, when, and with which token is readable at /v1/audit. An administrator asking after the fact is the only person in a position to act, and "the system did it" is not an answer they can use.

Self-hosting

The server runs on Node against SQLite by default, or Postgres by setting DATABASE_URL. Both are generated from one schema definition and pinned by a parity test, so self-hosting is the same product rather than a reduced edition. For air-gapped estates, the sync server and the shells never require an outbound connection to us.

Still deciding?

The fastest way to judge a marker is to try to break it. Run a paper, answer it badly on purpose, and read the reason next to every mark.