Developers

Elements embed

Compose signing UI into your React product with typed primitives — Provider + status + signer + signature-capture components you render inside your own page shell.

Integrate Elements in four steps

  1. 1

    Install the package

    Add @endorsed/elements to your React 18+ project. Peer deps are React and React DOM only — no vendor SDK sprawl.

  2. 2

    Mint a signing-session token server-side

    From your backend, POST /api/signing-sessions with the envelope id + signer email. The response contains a short-lived signing-session token scoped to that signer.

  3. 3

    Wrap your signing route in <EndorsedProvider>

    The provider carries your API config into the primitives — no prop drilling. Redeem the session token with useSigningSession() and render <EnvelopeStatus>, <SignerInfo>, and <SignatureField> inside your own layout.

  4. 4

    Handle signature submit + status callbacks

    useSignatureSubmit() posts the captured signature to /api/signing-sessions/:id/signature. Listen for status transitions and route the signer to your own success/decline pages when SigningSessionStatus flips.

Minimal embed example

A composable signing surface using the shipped primitives. Prerequisites: React 18+ and a signing-session token minted server-side. Expected output: a signer sees their envelope status, their identity, and a signature pad — all inside your product chrome.

tsx
import {
  EndorsedProvider,
  EnvelopeStatus,
  SignerInfo,
  SignatureField,
  useSigningSession,
} from '@endorsed/elements';

// 1. Wrap once at the app root (or per-signing-route).
export function App({ children }: { children: React.ReactNode }) {
  return (
    <EndorsedProvider
      baseUrl={process.env.NEXT_PUBLIC_ENDORSED_BASE_URL}
      // No API key in the browser. The provider only holds config.
    >
      {children}
    </EndorsedProvider>
  );
}

// 2. Render the signing surface. Compose these primitives into your
//    own page shell — headers, footers, and layout stay yours.
export function SigningPage({ sessionToken }: { sessionToken: string }) {
  const { status, envelope, signer } = useSigningSession(sessionToken);

  if (status === 'loading') return <p>Loading signing session…</p>;
  if (status === 'expired' || status === 'revoked') return <p>This link has expired.</p>;

  return (
    <section>
      <EnvelopeStatus value={envelope.status} />
      <SignerInfo values={{ name: signer.name, email: signer.email }} />
      <SignatureField
        onSubmitted={(result) => {
          // Advance your product state — redirect, mark task done, etc.
          console.log('Signature captured', result.signatureId);
        }}
      />
    </section>
  );
}

Elements ships composable primitives (Provider, status/signer display, signature capture). Compose the primitives above or embed the hosted signer via the signing-session URL.

What embed handles for you

📄

Document rendering

PDF rendering, zoom, scroll, and page navigation — cross-browser, including mobile Safari.

✍️

Signature capture

Draw, type, or upload signature. Consistent capture experience across devices without browser quirks.

🔐

Identity verification

OTP check is handled inside the embed. No separate authentication UI required in your product.

📋

Field navigation

Guided field-by-field navigation with required-field enforcement before submission is allowed.

Common questions

Elements embed — inside your product

The signing surface renders inline on your domain with your brand. Your product frame, your header, your navigation — EndorsedSign handles the document and field interaction.

Signer document list in the customer portal with populated statuses and actions
Elements embed rendered inside a fictional SaaS product. The signing surface sits inside the product chrome — no redirect, no iframe, no EndorsedSign branding visible.

Try Elements in your own sandbox tenant

Claim a sandbox via the quickstart, mint a signing-session token from your backend, and drop the primitives above into any React 18+ app.