Spondeo
Live demo · whitelabel-ready

Stripe-grade signing in your app. Restyle it live.

A real envelope, a real audit log, and the same three API calls you'd ship in production. Tweak the appearance below — the iframe updates instantly. Drop in a sample brand (or upload your own logo) to see how white-label signing looks for your customers.

AppearanceSDK-side. Changes instantly, no JWT re-mint.
Theme
Primary
Shape
Font
Palette
Buttons
LayoutChrome toggles. Also SDK-side.
Top bar
Density
Finish label
Toolbar
Decline
Terminal
Sender info
Mode
On complete
BrandingJWT-attested. Each change re-mints the signing URL.
Brand
Badge
Consent
Redirects
Where to send the signer on terminal state when the page is loaded outside an iframe (Stripe-Checkout-style). The /try demo runs the signer in an iframe, so these URLs are recorded on the JWT but won't fire here — they'd fire if you navigated to /sign/<jwt> directly.
Ready to start
Sample Mutual NDA
One-page sample NDA. Click below to mint a test envelope and embed the signing flow right here.
The three calls that drove this
// 1. Create an envelope from an uploaded document.
const envelope = await spondeo.envelopes.create({
  subject: 'Mutual NDA',
  document_id: 'doc_demo_nda',
  recipients: [{ name: 'Jane Roe', email: '[email protected]' }],
  send: true,
});

// 2. Mint a short-lived signing URL.
//    `display.branding` is server-attested and lives in the JWT —
//    the embedder cannot tamper with it. Branding requires the
//    Branding add-on in live mode; test mode is free.
const { signing_url } = await spondeo.envelopes.signingUrls.create({
  envelope_id: envelope.id,
  recipient_id: envelope.recipients[0].id,
  ttl_seconds: 600,
});

// 3. Hand the URL to the embed SDK.
//    `appearance` / `layout` / `copy` / `behavior` are SDK-side —
//    change any time without re-minting.
import { Spondeo } from '@spondeo/embed';
Spondeo.embed({
  url: signing_url,
  container: '#sign-here',
  appearance: {
    theme: 'light',
    variables: {
      colorPrimary: '#7c3aed',
      borderRadius: '8px',
      fontFamily: 'system-ui',
    },
  },
  layout: { topBar: 'show', density: 'comfortable' },
  onComplete: (e) => router.push(`/signed/${e.envelope_id}`),
});

What just happened

  1. POST /v1/envelopes with the sample document and a single recipient. Test-mode key, so no emails are sent.
  2. POST /v1/envelopes/{id}/recipients/{rid}/signing_url to mint a short-lived JWT — the equivalent of Stripe's client_secret. Pass display.branding here to attach a logo + brand name. Branding requires the add-on in live mode; test mode is free.
  3. Spondeo.embed({url, appearance}) from @spondeo/embed mounts the signing surface. The appearance, layout, and copy objects change any time without re-minting.

Try it in your app

Mint an API key from the dashboard, copy the snippet on the right, and you're live. Test-mode keys are free and never email anyone.