Skip to main content
The Embedded Player renders Edpire’s complete assessment UI inside a container on your page. The SDK fetches the assessment, handles every interaction, grades the submission and shows per-question feedback, all from one call. The learner never leaves your app. This is the Exam Hall mode from Two ways to ship. For the question-by-question alternative, see Custom Flow.
Why a server endpoint? You cannot call Edpire directly from the browser: your API key would sit in the JavaScript bundle for anyone to read. The token endpoint lets your server verify the learner from your own session, mint a short-lived single-use token, and send only that to the browser.
Fastest start: scaffold a ready-to-run example instead of wiring this by hand.
Both ship inside the @edpire/sdk npm package. Each has a README with next steps.

Step 1. Mint tokens on your server

Every integration needs this, whatever your frontend is.
Never trust the client for the learner ID. Resolve the learner from your server session. If you read a user ID from the request body, anyone can mint tokens as anyone else. createEdpireTokenHandler enforces this through resolveLearner.If some of your content is paid or restricted, check entitlement here too, not only on the page that renders the player. This endpoint is reachable on its own.
The token expires after 2 hours and is consumed when the learner submits. Mint a fresh one each time the learner opens the assessment. Minting does not invalidate a token already in use, so a learner with the assessment open in another tab is unaffected.

Step 2. Mount the player

<EdpireAssessmentPlayer> handles token fetching, mounting, unmounting and StrictMode double-invoke cleanup for you.
That is the entire integration.

React version support


Container sizing

The player fills its container, so you are responsible for sizing it. A container with no explicit height, or one constrained by centering utilities, collapses to zero and hides the player.
If your CSS framework applies global centering or max-width to #root or body (common in Vite and CRA templates), override those rules for the player container. A width: 1126px; margin: auto wrapper visually cuts off the player and can break RTL layout.

Allowed origins

The embed player is origin-scoped: it only loads from domains you explicitly allow. A blank player, or ORIGIN_NOT_ALLOWED in onError, almost always means this list.
  1. Go to edpire.com → Integrations → Security → Allowed Embed Origins
  2. Add every origin your app runs on, including staging and local development:
    • http://localhost:3000 (Next.js dev)
    • http://localhost:5173 (Vite dev)
    • https://yourapp.com (production)
  3. Save and reload
Origins are matched exactly: scheme, host and port. https://app.example.com does not cover https://www.app.example.com.There are two separate lists. Allowed Embed Origins governs the browser SDK. Allowed API & Redirect Origins governs return_url and REST CORS. An origin present in the second but missing from the first looks registered and still fails.
Native WebViews send no origin, or an opaque one like capacitor://localhost. Both are handled, so there is nothing to register for mobile.

Reference

EdpireAssessmentPlayerProps (React)

MountOptions (imperative)

Everything above applies, minus the React-only props. mount() takes the token directly rather than a tokenEndpoint.

mediaHandler

Required only if your assessment contains OpenResponse questions with file-upload or audio/video recording. Without it, those question types silently fail to submit.
upload receives (file, type) and must resolve to { url, mimeType? }. There is no progress callback. If you want a progress bar, track it in your own upload code and render it outside the player.

EmbedInstance

Safe to call from inside onComplete: the SDK defers the actual React unmount so it never fires mid-render.

EmbedResult

Passed to onComplete. Note the fields are snake_case, mirroring the API response.
If awaiting_manual_grading is true, the visible score is provisional: open-response answers still need a teacher. Listen for the submission.grading.completed webhook for the final score.

EmbedError


Advanced: bring your own data with AssessmentShell

EdpireAssessmentPlayer fetches the assessment client-side after mount and handles everything. Drop down to AssessmentShell only when you need to control data loading yourself: server-rendering the assessment for a faster first paint, pre-fetching before the learner navigates, or plugging into your own caching layer. AssessmentShell expects data in the runtime shape (AssessmentContent), not the raw REST Assessment. That conversion is yours.
Your onSubmit grades the attempt and returns a SubmitResult. Note that client.submit() returns GradeResult in snake_case while the shell expects SubmitResult in camelCase, so map between them on the server:
client.submit() returns per-question scores (exercise_results) but not the per-node visual feedback (exerciseFeedback) the shell uses to highlight answers inline. If you need both, use the Embedded Player above, which gets the full response automatically.

AssessmentShellProps

exerciseFeedback drives the inline per-question feedback. See the type catalog for ExerciseFeedbackData, QuestionFeedback and NodeFeedback.

Next steps

Custom Flow

Question-by-question instead, with your own UI around it.

Webhooks

Receive results server-side, which you want as the primary path.

Mobile and WebView

The same player in React Native, Flutter or native.

Troubleshooting

Blank player, token errors, styles behaving oddly.