Skip to navigation

Embed

Embed a SpreadSpace surface directly in your own application. Your users work with the spreading workspace or the document review panel without leaving your product, and without your page ever holding a SpreadSpace token.

A browser package renders the surface, React or plain JavaScript, and the SpreadSpace SDK for your server’s language mints the credential that authorizes it:

PackageRegistryRunsPurpose
@spreadspace/reactnpmBrowserRenders the embedded surface via <SpreadSpaceEmbed />.
@spreadspace/embednpmBrowserRenders the embedded surface with mount() in any page, as a module or a script tag. @spreadspace/react is a thin layer over it.
@spreadspace/sdknpmServerMints the short-lived session or handle that authorizes the embed, from TypeScript or Node.
spreadspacePyPIServerThe same mints from Python.
SpreadSpaceNuGetServerThe same mints from C#.

How it fits together

  1. Your backend uses a SpreadSpace SDK (or a direct API call) with an API key that holds the embed:write scope to mint a single-use handle or a loan-scoped session. Every sample reads that key from SPREADSPACE_EMBED_API_KEY; the Backend key stays in SPREADSPACE_API_KEY.
  2. Your app renders <SpreadSpaceEmbed /> from @spreadspace/react, or calls mount() from @spreadspace/embed in a page without React, and gives it a getHandle callback that fetches that handle from your backend.
  3. The browser package loads the returned signed_url into an iframe served from SpreadSpace’s origin. Inside the iframe, the handle is exchanged for a short-lived, loan-bound embed token that stays in the iframe and never reaches your page.

Install

npm i @spreadspace/react

The security model

Your page never holds a SpreadSpace token. The token is minted server-side, exchanged inside a same-origin iframe, and kept there. A handle is single-use, expires in seconds, and is worthless off SpreadSpace’s origin. The browser-facing token holds the scopes the mint names and is locked to a single loan. Read scopes are granted by mint authority; a write scope is granted only when the mint names it and only if the minting key holds it. The only grantable writes are the explicit per-mint upload, review and spread scopes (documents:write, extractions:write, extractions:edit, spreads:write), which stay bound to that same loan. A leaked token therefore cannot reach other loans or mint further tokens. The embed:write scope, held only by your server-side API key, is the control point: revoking it immediately severs every issued token and in-flight handle.

Persistent user state

Pass an optional external_user_id (your app’s opaque identifier for the viewing user, up to 256 characters) when minting a session or iframe handle. Sessions minted with the same id share server-kept state for that user: board arrangements, view preferences, and saved memo templates survive across that user’s sessions and devices. Omit it and each session starts from defaults.

The mint response says which mode you got. persistence is user when an external_user_id was supplied and session when it was not, and session means nothing the viewer arranges is ever saved.

The id also comes back to you: when that user finalizes a spread, the attribute snapshot carries it as finalized_by_external_user_id, so your backend can say who finalized from its own user table. SpreadSpace never has to hand a person’s name to your service key.

You can also pass an optional display_name (up to 120 characters) beside the id. The workspace shows it as that user’s name on the spreads they save and finalize, on their comments and in live presence. It requires external_user_id in the same request.

How the numbers reach your backend

The analyst finishes the spread inside the embed and finalizes it there. Your backend receives a spread.finalized webhook naming the loan and the snapshot it just created, then reads that snapshot, the figures as the analyst approved them, by id with GET /api/loans/{loanId}/attributes/{snapshotId} (the same attribute snapshot the workspace produces) straight into your own fields. The snapshot contains the figures the analyst approved. If the analyst later reopens the spread to revise it, spread.reopened names that same snapshot so you can mark your copy stale until the next finalize arrives.

A session whose user is expected to finalize must be minted with spreads:write (or the wider extractions:write). The SDK’s webhook receiver reads the snapshot the event names for you on spread.finalized, so the handler you write is the half that stores it.

Quick starts