Examplary
  • Start for free
    Developer docs

    Developer changelog

    Changes to the API, SDKs, embeds, and question type platform, in chronological order.

    1. Write your own entries to the audit log

      Organizations get a full audit trail of significant actions, and you've been able to read it over the API for a while. Now your app can write to it as well — record an action it took in its own system so it lands in the same timeline as everything Examplary logs itself.

      POST /audit-logs takes an action in resource.action form, the object it acted on, and optional session, reason and before/after snapshots. It needs the new audit-logs:write scope — not granted by default — and only OAuth apps can call it; JWT and API-key callers get a 403. Entries are attributed to the token's own actor and marked as coming from an app, so they're never mistaken for Examplary's own.

    2. Store your own metadata on users

      Every user now carries a metadata field: a free-form map of your own keys and values. Hang an external reference straight off the Examplary user — the id for a person in your SIS, LMS or CRM — instead of keeping a separate mapping table on your side.

      Set it when you create a user or with PATCH /users/{id} (needs users:write), and read it back from GET /users or a single user (users:read). A patch merges into whatever is already there, and setting a key to null clears it. Values are scalars — a string, number or boolean — not nested JSON.

    3. Grade answers that contain files

      Question types that collect a file — an uploaded document, an image, a voice recording — used to hand the grading AI nothing but the file's URL as text. Now the file itself can go into the prompt.

      Add fileInputs to a question type's grading object: a JSONata expression that starts with = and resolves to a file URL or an array of URLs. It has the submitted answer and the question configuration in scope, just like responseProcessing.condition.

      {
        "grading": {
          "enabled": true,
          "fileInputs": "=answer.value"
        }
      }
      

      The files are fetched and attached to the end of the grading prompt, so the AI reads the document, image or audio directly instead of guessing from a link. Only files hosted on the Examplary media CDN are attached; any other URL is skipped. See the grading docs for the details.

    4. Choose where AI processing happens

      Workspaces on Examplary for organizations can now keep AI processing — generating questions, grading, feedback and scanning answer sheets — inside the EU. It's a workspace setting, so you can set it with PATCH /org:

      { "settings": { "aiRegion": "eu" } }
      

      settings.aiRegion is either global (requests go wherever there's capacity) or eu (processing and any files sent along with it stay in the EU). For organizations based in the European Economic Area, eu is the default; for everyone else, it's global. It applies to every request from then on, and each change lands in the audit log as org.ai_region_changed.

      The call needs the orgs:write scope and an Owner or Admin. Changing the region on a plan that doesn't include it returns a 403.

      The same toggle is under Account → Access & domains in the dashboard, and the data residency guide has the details.

    5. Deprecate a question type

      You can now set deprecated: true in a question type's definition to retire it gracefully. Existing questions of that type keep rendering, grading, regenerating and exporting exactly as before — but no new ones can be created, and orgs that haven't already enabled it can no longer discover or enable it.

      It's the clean way to phase out a type you've replaced. Setting public: false looks like it would do the same, but it also stops other orgs from resolving the definitions of questions they already have, so those questions stop rendering. See publishing question types for the details.

    6. POST /exams/{id} and POST /folders/{id} are gone

    7. Check the quality of a question over the API

      GET /exams/{id}/questions/{questionId}/quality returns Examplary's read on how well a question is written — the same analysis the editor shows.

      Useful if you're generating questions programmatically and want to flag the weak ones for a human before a test goes out.

    8. Rename the labels in embedded flows

      "Student level" doesn't fit every product. You can now override individual UI strings in any embed session by adding a strings object to theme:

      {
        "theme": {
          "strings": {
            "account.attributes.student-level-name": "Candidate level",
            "account.attributes.subject-name": "Assessment field"
          }
        }
      }
      

      To find the key for a label, open the Examplary dev tools with Shift + Control + Tilde, click the language icon and switch to Translation keys. Anything you don't override keeps its normal wording.

      More in theme options.

    9. Hide fields in the exam generation embed

      The generate-exam embed flow has five new presets for trimming down the form your users see: hideSubject, hideStudentLevel, hideDuration, hideTaxonomy and hideQuestionTypes.

      They pair nicely with the presets you were already sending. Set studentLevel and hideStudentLevel together, for example, and the level is applied without your users ever seeing the field — handy when your product already knows the answer.

      All of them are listed in the exam generation flow docs.

    10. Results summaries over the API