Mint Starter Kit

Ceremonies

Embed Signing in a Mobile App

Embed the SignatureAPI signing interface in your mobile app using a WebView

You can embed the signing ceremony directly in your mobile app using a WebView. The recipient signs inside your app, without switching to an external browser.

Complete, runnable example: the mobile integration demo has an iOS app, an Android app, a demo server, and end-to-end tests. The iOS and Android guides take their samples from it.

You need both:

  • A server that creates the envelope and returns the ceremony URL.
  • A client (your mobile app) that shows the ceremony and reacts to its events.

How it works

sequenceDiagram
    participant App as Mobile app
    participant Server as Your server
    participant API as SignatureAPI
    participant View as WebView
    App->>Server: Ask for the signing link
    Server->>API: Create the envelope with custom authentication
    API-->>Server: Ceremony URL
    Server-->>App: Ceremony URL
    App->>View: Load the URL with embedded=true and an event_delivery value
    Note over View: The recipient signs
    View->>App: Send the event: completed, canceled, declined, or failed
    App->>Server: Did the recipient sign?
    Server->>API: Read the envelope
    API-->>Server: Recipient status is completed
    Server-->>App: Confirmed, show the result screen
  1. Your server creates an envelope with custom authentication. SignatureAPI returns the ceremony URL instead of emailing it.
  2. Your app gets the URL from your server and loads it in a WebView, with embedded=true and an event_delivery value appended.
  3. When the ceremony ends, it sends an event: completed, canceled, declined, or failed. Your app closes the WebView and shows the next screen.
  4. Your server confirms the outcome through the API or a webhook before acting on it.

Choose how to load the ceremony

There are three ways to receive events from a ceremony in a WebView:

flowchart TD
    Start([Show the ceremony in a WebView]) --> Q1{Do you already embed it in a web page with an iframe?}
    Q1 -- Yes --> Iframe[Local page with an iframe<br/>event_delivery=message<br/>needs embeddable_in]
    Q1 -- No --> Q2{Do you prefer a JavaScript message<br/>over a navigation?}
    Q2 -- No --> Redirect[Top-level WebView<br/>event_delivery=redirect<br/>recommended]
    Q2 -- Yes --> Message[Top-level WebView<br/>event_delivery=message<br/>document-start script]
Top-level WebView with redirect (recommended)Top-level WebView with messageLocal page with an iframe
What the WebView loadsThe ceremony URL itselfThe ceremony URL itselfA page from your app that puts the ceremony in an <iframe>
Event deliveryevent_delivery=redirectevent_delivery=messageevent_delivery=message
embeddable_inNot neededNot neededThe local page’s origin, such as https://app.example.invalid
How your app gets eventsCatch the signatureapi-message:// navigation and cancel itA script injected at document start forwards the message to native codeThe local page checks each message and forwards it to native code
When to use itMost appsYour app prefers a JavaScript message and can inject a document-start scriptYou share a web SDK page, or need your own HTML around the ceremony

With redirect delivery, the ceremony navigates the WebView to a URL such as signatureapi-message://ceremony.completed. This is a client-side navigation, so no request reaches the network. Only the WebView’s navigation handler sees it: HTTP-layer interception never does.

With message delivery in a top-level WebView, the ceremony posts to its own window. Your app injects a script at document start that forwards the message to native code. The script must accept only messages whose origin is the ceremony’s and whose source is the page’s own window. For the code, see iOS and Android.

With a local page, load its HTML with a synthetic https base URL. The WebView fetches nothing from that origin. List the same origin in the ceremony’s embeddable_in.

The iOS and Android guides cover all three approaches. The React Native guide covers the top-level WebView.

For a complete, runnable app with a server, see the SignatureAPI mobile integration demo.

Create the ceremony on your server

Your server creates the envelope with these settings on the recipient:

  • custom authentication, so the response includes the ceremony URL.
  • delivery_type set to "none" if your app distributes the signed documents itself.
  • No redirect_url. Embedded ceremonies ignore it.
  • No embeddable_in for a top-level WebView. For a local page, list that page’s origin.
  • Optionally, redirect_delay set to 0 so your app shows its own result screen right away.
// POST https://api.signatureapi.com/v1/envelopes
// X-API-Key: key_test_...
// Content-Type: application/json

{
  "title": "Service Agreement",
  "documents": [
    {
      "url": "https://pub-9cb75390636c4a8a83a6f76da33d7f45.r2.dev/privacy-placeholder.pdf",
      "places": [
        {
          "key": "client_signature",
          "type": "signature",
          "recipient_key": "client"
        }
      ]
    }
  ],
  "recipients": [
    {
      "type": "signer",
      "key": "client",
      "name": "Jane Doe",
      "email": "jane@example.com",
      "delivery_type": "none",
      "ceremony": {
        "authentication": [
          {
            "type": "custom",
            "provider": "My App",
            "data": {
              "user_id": "usr_12345"
            }
          }
        ],
        "redirect_delay": 0
      }
    }
  ]
}

Wait until the envelope leaves processing (read it with GET /v1/envelopes/{id}), then read recipients[].ceremony.url. Return it to your app.

Rules for every platform

  • Keep your API key on your server. Never call SignatureAPI from the app. An API key in an app bundle is exposed to anyone who installs the app.
  • Leave redirect_url unset. Embedded ceremonies send events instead of redirecting.
  • Confirm the outcome on your server. An event is a UI signal, not proof. Read the envelope (GET /v1/envelopes/{id}) or use a webhook before acting on it. See Confirm the outcome on your server.
  • Branch on error_type. For ceremony.failed, treat an unknown value as a generic failure. Don’t show error_message to recipients. See Error types.
  • Keep the default WebView settings. They work, except that Android needs JavaScript turned on. The ceremony needs no cookies or storage. See Browser requirements for the hosts to allow.
  • Treat the URL as a credential. Don’t log it or store it on the device. To resume, ask your server for the current URL. See A new URL on every read.
  • Test with real input. The ceremony completes only after input a person produces. See Automated testing.

Try it

Use your test API key to create a test envelope and ceremony. Test envelopes don’t send emails, so you can try your integration without affecting real recipients. Review the results in your Dashboard.

Keep learning