Examplary
  • Start for free

    Developer changelog

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

    1. 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 (the default — requests go wherever there's capacity) or eu (processing and any files sent along with it stay in the EU). 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.

    2. 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.

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

    4. 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.

    5. 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.

    6. 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.

    7. Results summaries over the API

    8. The API is stricter about CORS

      The API used to reflect any origin back in its CORS headers. It now only does that for first-party Examplary origins and an organization's own active custom domain.

      If you were calling the API straight from browser JavaScript on your own domain, those requests will start failing. Server-to-server calls aren't affected — CORS is a browser-only restriction, so anything running on your backend carries on as before. If you need something in the browser, Embed Sessions are built for exactly that.

      LTI, OAuth and the public endpoints stay open, since they're meant to be called from places we don't control.

    9. Rate limits are now written down

      Most API endpoints are rate limited, per user or per IP address depending on the endpoint. That's been true for a while — you just had to find out by running into one.

      Every endpoint reference page now has a Rate limit section with its own limit, and there's a summary on the REST API overview. Go over it and you'll get a 429 with a Retry-After header telling you how long to wait.

      We also tightened the limits on the AI and email endpoints, and loosened them on the student-facing ones — a whole class taking a test from one school building shares a single IP address, and that shouldn't look like abuse.

    10. Release grades and assign sessions over the API