Skip to main content
You can embed the signing interface directly in your mobile app using a WebView. The signer completes the ceremony inside your app without being redirected to an external browser. You need both:
  • A server to create an envelope and get a ceremony URL.
  • A client (your mobile app) to display the ceremony to the recipient.

Server Side

The server-side setup for mobile embedding is the same as for web embedding. Your server creates an envelope with a recipient whose ceremony uses Custom Authentication, then returns the ceremony URL to your mobile app. Follow the server-side steps in the Embed Signing in a Web App guide, then return here for the mobile-specific client implementation.
Never call the SignatureAPI API directly from your mobile app. Your API key would be exposed in the app bundle. Always fetch the ceremony URL from your own backend.

Client Side (React Native)

Install the WebView package

Install react-native-webview:
npm install react-native-webview

Build the signing component

Create a SignatureApiWebView component that loads the ceremony and handles the terminal events: ceremony.completed, ceremony.canceled, and ceremony.failed. Mobile apps use event_delivery=redirect instead of event_delivery=message. When the ceremony reaches a terminal state, the signing interface redirects the WebView to a signatureapi-message:// URL. Your app intercepts that navigation and responds accordingly.
import React, { useCallback } from 'react';
import { WebView, WebViewNavigation } from 'react-native-webview';

interface SignatureApiWebViewProps {
  ceremonyUrl: string;
}

export function SignatureApiWebView(props: SignatureApiWebViewProps) {
  const { ceremonyUrl } = props;

  const [showWebview, setShowWebview] = React.useState<boolean>(true);

  // Append query parameters to make the ceremony embeddable.
  // Use event_delivery=redirect so events arrive as interceptable
  // navigations rather than JavaScript messages.
  const embeddedCeremonyUrl =
    ceremonyUrl + '&embedded=true&event_delivery=redirect';

  const handleNavigation = useCallback(
    (navigationState: WebViewNavigation): void => {
      try {
        const parsedUrl = new URL(navigationState.url);

        // Intercept signatureapi-message:// URLs
        if (parsedUrl.protocol !== 'signatureapi-message:') return;

        const eventType = parsedUrl.host;

        switch (eventType) {
          case 'ceremony.completed':
            // The recipient finished signing
            setShowWebview(false);
            break;
          case 'ceremony.canceled':
            // The recipient canceled the ceremony
            setShowWebview(false);
            break;
          case 'ceremony.failed':
            // An error prevented the ceremony from completing
            setShowWebview(false);
            break;
          default:
            console.log(`Unhandled event: ${eventType}`);
        }
      } catch (error) {
        console.error('Error handling navigation:', error);
      }
    },
    []
  );

  if (!showWebview) return null;

  return (
    <WebView
      source={{ uri: embeddedCeremonyUrl }}
      onNavigationStateChange={handleNavigation}
      originWhitelist={['*']}
      style={{ flex: 1 }}
    />
  );
}

Use the component

Your app fetches the ceremony URL from your backend and passes it to the component:
// Fetch the ceremony URL from your backend, then render:
const ceremonyUrl =
  'https://sign.signatureapi.com/en/start?token=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...';

<SignatureApiWebView ceremonyUrl={ceremonyUrl} />;

How events are delivered

When the ceremony ends, the signing interface issues a redirect to a signatureapi-message:// URL. The host portion of the URL identifies the event type:
URLEvent
signatureapi-message://ceremony.completedRecipient finished signing
signatureapi-message://ceremony.canceledRecipient canceled
signatureapi-message://ceremony.failedAn error occurred
For ceremony.failed, the URL includes error_type and error_message query parameters with details about the failure. See Ceremony Events for the full reference.

iOS and Android

Native iOS and Android apps follow the same pattern. Load the ceremony URL (with embedded=true and event_delivery=redirect appended) in a WebView, then intercept navigation to signatureapi-message:// URLs to handle events.
  • iOS (WKWebView): Implement webView(_:decidePolicyFor:decisionHandler:) in your WKNavigationDelegate. When the URL scheme is signatureapi-message, cancel the navigation and handle the event.
  • Android (WebView): Override shouldOverrideUrlLoading in your WebViewClient. When the URL scheme is signatureapi-message, return true and handle the event.

Try It

Use your test API key to create a test envelope and ceremony. Test envelopes won’t send emails, so you can iterate quickly without affecting real recipients. Review the results in your dashboard.

Keep Learning