Summer release note - announcements, surveys & registrations go API-first, MCP & OAuth 2.1 for agentic systems
Two months of work, one release note. Edusign's API can now be driven by AI agents over OAuth 2.1, and three journeys that used to require the back-office, announcing, surveying, and opening registrations, are fully automatable end to end.
Everything below is live in production today.
TL;DR🤖 Connect Claude (or any MCP host) to your Edusign account — OAuth 2.1, PKCE, read/write scopes.
📣📝🎟️ Three journeys go API-first — push announcements, survey templates, training registration forms.
✅ 20+ new endpoints, 18 routes out of beta, and a full timezone-consistency pass.
🤖 Bring your own AI agent
Remote MCP server · NEW
NEWhttps://mcp.edusign.com
Connect Claude, ChatGPT or any MCP-compatible host to your Edusign account and let it read and act on your data — in your users' name, with your permissions.
The server holds no privileges of its own: it verifies your token and replays it against the API, which stays the sole authorization judge. No shared API key, no standing access.
OAuth 2.1 authentication · NEW
NEWhttps://auth.edusign.com/api/auth
The API now accepts OAuth 2.1 bearer tokens alongside classic API keys. Authorization code with PKCE, refresh tokens, dynamic client registration and RFC 9728 protected-resource discovery — so compliant clients configure themselves.
| Scope | Grants |
|---|---|
edusign:api.read | Every read endpoint |
edusign:api.write | Creates, updates, archives |
offline_access | A refresh token, so long-running integrations stay connected |
📣 Reach your learners — from your own systems
Send a push announcement · NEW
NEWPOST /v3/notifications/announcements → reference
Push a message to your white-label app straight from your LMS, ERP or CRM. Enrolment confirmed, room changed, deadline tomorrow — your systems already know it, now they can say it.
- Choose your audience — everyone, authenticated users only, or up to 1,000 targeted users or groups, addressed by Edusign ID or by your own external reference.
- Choose your channel —
push_and_inbox(push plus a trace in the app's Messages tab) orpush_only(lock screen only). - Schedule it — set
sendAtto any future ISO 8601 datetime and get a202; omit it and it goes out now. - Add links — inline Markdown links render as real links in the in-app message.
- Speak their language —
fr,en,es,it, defaulting to the school language.
Titles are capped at 60 characters, bodies at 1,500 — 120 for push_only, where the OS only shows a preview.
Availability: schools with a white-label app and the Messaging feature enabled.
📝 Own your feedback loop
Survey templates, full lifecycle · NEW
NEW| Endpoint | ||
|---|---|---|
| Create | POST /v3/survey-templates | reference |
| Replace | PUT /v3/survey-templates/:id | reference · by reference |
| Archive | DELETE /v3/survey-templates/:id | reference · by reference |
| Restore | POST /v3/survey-templates/:id/restore | reference · by reference |
Version your questionnaires in your own repository and push them to Edusign — no more copy-pasting questions into the back-office when a form changes. Every route has a by-reference-id twin, so your connector never has to store an Edusign ID.
Know when a survey actually goes out · NEW
NEWon_survey_sent
on_scheduled_survey_sent
Two new webhook events close the loop between "I scheduled a survey" and "it reached its recipients":
on_survey_sentfires per recipient, on manual and scheduled sends alike, carryingsurveyId,recipientIdandrecipientType(student,professororexternal).on_scheduled_survey_sentfires once per scheduled batch, when the auto-send job completes, carryingsurveyId,recipientCountand the originatingcourseIdortrainingId.
Subscribe for a per-person audit trail, for a single "your programmed survey went out" signal, or both. Each is also available as an automation trigger.
Find the responses you're looking for · IMPROVED
IMPROVEDGET /v3/surveys accepts completionDateFrom and completionDateTo to fetch only the responses submitted in a window — the incremental pull your reporting job actually wants. Responses now also carry the respondent's externalReferenceId, so you can join them to your own records without a lookup round-trip.
🎟️ Open your trainings to registrations
Training registration forms · NEW
NEWGET · PUT /v3/trainings/:id/registration-form → read · configure
Configure the public registration form of a training program and retrieve its link — so a new session published on your website can open its own registrations, automatically. Custom variables are referenced by name, which keeps payloads readable and portable across environments. Both routes have by-reference-id twins.
🏫 Rooms, groups and rosters
Classrooms CRUD · NEW
NEW| Method | Endpoint | |
|---|---|---|
GET | /v3/classrooms | reference |
POST | /v3/classrooms | reference |
PATCH | /v3/classrooms/:id | reference · by reference |
DELETE | /v3/classrooms/:id | reference · by reference |
Sync your room inventory like any other resource, by Edusign ID or by external reference. Each classroom carries an optional linkTo URL — the natural home for a virtual-classroom or video-conference link.
Archive and restore a group · NEW
NEWDELETE /v3/groups/:id → reference · by reference
POST /v3/groups/:groupId/restore → reference · by reference
A soft archive with explicit semantics — worth reading before you wire it up:
- The group is hidden and detached from its parent. Student memberships are preserved.
- Direct child groups are orphaned, not archived — their parent link is cleared and they stay active.
- No cascade to courses, students, trainings or alerts.
- Archiving an already-archived group returns
409 ARCHIVED_GROUP_EXISTS; restoring an active one returns409 GROUP_NOT_ARCHIVED. - A restored group comes back as a root group — the previous parent link is not re-established.
GROUP_DELETEDandGROUP_UNREMOVEDwebhooks fire on success.
Restore an archived professor · NEW
NEWPOST /v3/professors/:professorId/restore → reference · by reference
Closes the archive/restore loop for professors, matching students and groups.
Batch upsert groups, now addressable by internal ID · IMPROVED
IMPROVEDPOST /v3/groups/batch-upsert matches on externalReferenceId or groupId, and accepts parentGroupId to build hierarchies in one pass. Circular hierarchies are rejected per item (CIRCULAR_HIERARCHY) instead of corrupting your tree. Batch assign students to groups now handles up to 1,000 assignments per call.
Unarchive during a training batch upsert · IMPROVED
IMPROVEDPOST /v3/trainings/batch-upsert accepts options.allowUnarchive to bring an archived training back and update it in the same call, instead of failing with ARCHIVED_TRAINING_EXISTS.
🔄 Keep your systems in sync
Incremental student sync · IMPROVED
IMPROVEDGET /v3/students accepts updatedAfter (ISO 8601) to pull only what changed since your last run, and isArchived to include or isolate archived students. Nightly full-table syncs can retire.
See your webhook registrations · NEW
NEWGET /v3/webhooks → reference
List the webhooks configured for your school, paginated and filterable. Debugging "why didn't I receive that event?" no longer requires opening a ticket.
✅ Out of beta
18 high-usage routes are now stable. Selection was driven by real 30-day production usage across students, professors, courses, groups, subjects and assessments — the [BETA] tag is gone from the reference and from the OpenAPI spec. Same paths, same payloads: no action needed.
🛠️ Fixed & hardened
Dates behave the same on the way in and on the way out · FIXED
FIXEDWe found and closed an asymmetry: some resources persisted datetimes in UTC while reading them back in the school's timezone, which could shift a value by the school's offset. Courses, assessments, submissions, subjects, grades, trainings and surveys now consistently store and return datetimes in the school's timezone.
Validation errors you can forward to a user · IMPROVED
IMPROVEDSchema validation messages were rewritten in plain wording — "body must be at most 1500 characters" rather than raw validator output — so you can surface them in your own UI without translating them first.
One limit for external references, everywhere · IMPROVED
IMPROVEDexternalReferenceId is capped at 64 characters and externalReferenceType at 30 across every resource; these previously varied by domain. Group logoUrl now accepts only http(s) URLs.
More accurate batch responses · IMPROVED
IMPROVEDupdatedFields reports only genuinely changed fields, and no-op updates no longer fire TRAINING_EDITED. Batch assignment rejects archived groups and duplicate pairs up front.
🗒️ Also live, and now fully documented
Shipped over the spring and never given a proper announcement — every one of these has a reference page today:
- Students — archive / restore, search, link externals, bulk upsert cards
- Professors — archive and batch upsert
- Courses — partial update, batch upsert, assign students, remove teachers
- Groups — replace a group's students
- Assessments — the full assessment and submission surface, including batch upsert
📌 Good to know
- Nothing breaking. Every change above is additive. Existing calls and API keys behave exactly as before.
apiId/apiTyperemain deprecated in favour ofexternalReferenceId/externalReferenceType. They still work; new integrations should use the standardized fields.by-reference-ideverywhere. Every new mutation route ships with an external-reference twin, so a connector never has to persist an Edusign ID.

