Verdocs - Developer Documentation

Embedded signing in React

Put Verdocs signing inside your own React app: send an envelope from your server, route the signer to your page, render the signer, and know when they are done.

This walks the whole path for a React application: create an envelope from your backend, get the signer to a route you own, render the signing experience inline, and find out when it completes. The signer never leaves your product and never sees a Verdocs URL.

There are two packages involved and they do different jobs. @verdocs/js-sdk talks to the API and belongs on your server. @verdocs/web-sdk-react renders the UI and belongs in your React app.

1. Install

npm install @verdocs/web-sdk-react   # your React app
npm install @verdocs/js-sdk          # your server

2. Create the envelope on your server

Envelope creation needs your API credentials, so it happens server side. Never put a client secret in browser code.

import {VerdocsEndpoint, authenticate, createEnvelope} from '@verdocs/js-sdk';

const endpoint = new VerdocsEndpoint();

// authenticate() returns the tokens but does not attach them, so set it yourself.
const {access_token} = await authenticate(endpoint, {
  grant_type: 'client_credentials',
  client_id: process.env.VERDOCS_CLIENT_ID!,
  client_secret: process.env.VERDOCS_CLIENT_SECRET!,
});
endpoint.setToken(access_token);

const envelope = await createEnvelope(endpoint, {
  template_id: '8e0b...c41a',
  name: 'Mutual NDA',
  recipients: [{role_name: 'Signer', email: 'ada@acme.com', first_name: 'Ada', last_name: 'Lovelace'}],
});

See Server workflow with static templates for the full set of options, and Send an envelope without a template if you are uploading a PDF directly instead.

3. Get the signer to your page

The response carries one recipient entry per signer, each with the three values the signing component needs: the envelope ID, the role, and an invite code. Build your own URL from them:

https://yourapp.com/sign/:envelopeId/:roleName/:inviteCode

By default Verdocs emails the signer a link to its own hosted signing page. To send them to your route instead, suppress the Verdocs notification and send your own message. Bring-your-own notification covers exactly that, and it is the step most people miss on the first try.

The invite code is a bearer credential for that one envelope and that one role. Treat it like a password: it belongs in the link you send the signer and nowhere else.

4. Render the signer

import {useRef} from 'react';
import {useParams} from 'react-router-dom';
import {VerdocsEndpoint} from '@verdocs/js-sdk';
import {VerdocsSign} from '@verdocs/web-sdk-react';

export const SignPage = () => {
  const {envelopeId = '', roleName = '', inviteCode = ''} = useParams();

  // sessionType: 'signing' means the signer is never asked to log in or create
  // an account. Held in a ref so a re-render does not rebuild the session.
  const endpoint = useRef(new VerdocsEndpoint({sessionType: 'signing'}));

  return (
    <VerdocsSign
      endpoint={endpoint.current}
      envelopeId={envelopeId}
      roleId={roleName}
      inviteCode={inviteCode}
      onEnvelopeUpdated={(e: any) => {
        if (e.detail?.event === 'submitted') {
          // The signer has finished. Route them wherever makes sense in your app.
        }
      }}
      onSdkError={(e: any) => console.error('Verdocs signing error', e.detail)}
    />
  );
};

VerdocsSign fills its container, so give it a parent with a real height. It renders the document, the fields, the signature and initial dialogs, and any authentication the recipient requires, including passcode, SMS, ID scan, and KBA. You do not wire those up separately; see the recipient auth ladder for what each one asks of the signer.

The props

PropWhat it is
endpointA VerdocsEndpoint with sessionType: 'signing'. Omit it and the component builds one with the same default.
envelopeIdThe envelope being signed.
roleIdThe recipient's role name, for example Signer.
inviteCodeThe invite code for that recipient.
headerTargetIdThe ID of a <div> you own. The component moves its header there on first render, which is how you control placement and scroll behavior. Applied once, so do not render that container conditionally.
toolbarStylecontrols or menu.

The events

EventWhen it fires
onEnvelopeLoadedThe envelope is loaded and about to render. Useful for analytics.
onEnvelopeUpdatedSomething changed. Check e.detail.event for submitted to detect completion.
onSdkErrorSomething went wrong. Log it; do not leave the signer staring at an empty box.

5. Confirm completion on your server

onEnvelopeUpdated fires in the signer's browser, which makes it right for updating your UI and wrong for anything that matters. A browser can close mid-submit and a client event can be forged.

Use webhooks for the authoritative signal, and read Securing your webhooks before you trust the payload. Treat the client event as a hint and the webhook as the fact.

One thing worth knowing: an envelope can report complete before the signed PDF and audit certificate have finished generating. If your flow downloads the document immediately on completion, wait for the event that says the artifacts are ready rather than the one that says signing finished. The FAQ covers the distinction.

Branding

Signing inherits the brand on the envelope's organization, so colors, logo, and disclaimers follow without any work in your app. To match your own styles more closely, override the CSS variables:

:root {
  --verdocs-primary-color: #654dcb;
  --verdocs-button-radius: 999px;
  --verdocs-field-background: #8dc63f1a;
}

Styling has the full variable reference.

If you cannot use Web Components

Some environments, older Angular versions and WordPress among them, cannot host custom elements. IFRAME embeds gives you the same flow with less styling control.

Vue, Angular, and vanilla

The same component ships for every framework; only the wrapper import changes. Get started with the Web SDK covers the others, and Components is a live Storybook of everything available.

On this page