Create an Embedded Signing Experience
Embedding the eSign experience directly into your application provides a seamless, white-labeled signing interface that keeps users within your workflow. Instead of redirecting signers to their email or an external page, you can integrate the complete signing experience right into your application using iframes.
This guide walks you through creating an embedded signing experience from start to finish.
Why Use Embedded Signing?
Benefits of embedding the signing experience:
- Seamless user experience - Users never leave your application
- Complete branding control - Customize colors, fonts, and styling to match your brand
- Higher conversion rates - Reduce friction in the signing process
- Additional security - Control access within your authenticated sessions
Overview
Creating an embedded signing experience involves four main steps:
- Upload a PDF document to the system
- Create an eSign transaction with participants and tags
- Generate a customized iframe URL with your branding
- Embed the signing interface in your application
Prerequisites
Before you begin, ensure you have:
- A valid Bearer token (JWT) for authentication
- At least one PDF document ready for upload
- Basic HTML/JavaScript knowledge for embedding
- Familiarity with eSign transactions
All API requests must include the following header:
Authorization: Bearer <your_access_token>
Content-Type: application/json
Step 1: Upload Your Document
First, upload your PDF file to the system.
Endpoint
POST /documents/upload
Request (multipart/form-data)
curl -X POST "https://api.sign.stewart.com/documents/upload" \
-H "Authorization: Bearer <token>" \
-F "files=@EmploymentContract.pdf"
Successful Response
[
{
"file": "EmploymentContract.pdf",
"status": "uploaded",
"StoragePath": "org-uuid/EmploymentContract.pdf"
}
]
Save the StoragePath from the response — you'll need it to create your transaction in the next step.
Step 2: Create an eSign Transaction
Once your document is uploaded, create a transaction that defines participants, documents, and signing fields (tags).
Endpoint
POST /transactions
Important: Generate UUIDs
Before making the request, generate unique UUIDs for:
- Each document's
idfield - Each participant's
idfield
You can generate UUIDs using online tools, programming libraries, or command-line utilities:
# Generate UUID
uuidgen
# Example output: 391866a6-8ebb-4533-b6ab-c7bb4d6fbd38
Example Request
curl -X POST "https://api.sign.stewart.com/transactions" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"notifyParticipants": {
"email": false // disable email sends from the system (optional)
},
"documents": [
{
"id": "391866a6-8ebb-4533-b6ab-c7bb4d6fbd38",
"StoragePath": "org-uuid/EmploymentContract.pdf",
"title": "Employment Agreement",
"description": "Please review and sign your employment agreement",
"sessionType": "esign",
"readOnly": false,
"tags": [
{
"type": "SIGNHERETAGTEMPLATEANNOTATION",
"x": 100,
"y": 150,
"width": 150,
"height": 34,
"page": 0,
"signerId": "37da192e-6420-4b9c-9951-a979eeaf8889",
"required": true
},
{
"type": "DATETEMPLATE",
"x": 270,
"y": 150,
"width": 100,
"height": 20,
"page": 0,
"signerId": "37da192e-6420-4b9c-9951-a979eeaf8889",
"dateFormat": "MM/DD/YYYY"
},
{
"type": "FULLNAMETEMPLATE",
"x": 100,
"y": 190,
"width": 150,
"height": 20,
"page": 0,
"signerId": "37da192e-6420-4b9c-9951-a979eeaf8889"
}
]
}
],
"participants": [
{
"id": "37da192e-6420-4b9c-9951-a979eeaf8889",
"email": "jane.smith@example.com",
"firstName": "Jane",
"lastName": "Smith",
"type": "signer"
}
],
"status": "esign_pending"
}'
Example Successful Response
{
"id": "transaction-uuid-here",
"esignId": "357aa7c7-16fd-4a2c-bd58-23da1f76fdd5",
"documents": [
{
"id": "391866a6-8ebb-4533-b6ab-c7bb4d6fbd38",
"title": "Employment Agreement",
"StoragePath": "org-uuid/EmploymentContract.pdf",
"sessionType": "esign"
}
],
"participants": [
{
"id": "37da192e-6420-4b9c-9951-a979eeaf8889",
"email": "jane.smith@example.com",
"firstName": "Jane",
"lastName": "Smith",
"type": "signer"
}
],
"status": "esign_pending"
}
Save both the esignId and the participant id from the response. You'll need these values to generate the iframe URL in the next step.
For more details on tags and transaction creation, see:
Step 3: Generate the iFrame URL
Generate a customized iframe URL that matches your brand's look and feel.
Endpoint
POST /iframe-request
Request Body
The iframe request accepts two main sections:
type: Set to"esign"for eSignature workflowsstyle: Customize colors, fonts, and appearancedata: Specify the transaction and participant(s)
Style Customization Options
| Property | Type | Description | Example |
|---|---|---|---|
primaryColor | Hex Color | Main brand color for buttons and highlights | #006837 |
secondaryColor | Hex Color | Background color for secondary elements | #f5f5f5 |
fontType | Font Family | Custom font (must be web-safe or loaded) | Arial, sans-serif |
textColor | Hex Color | Main text color | #333333 |
background | Hex Color | Page background color | #ffffff |
successColor | Hex Color | Success message color | #28a745 |
errorColor | Hex Color | Error message color | #dc3545 |
infoColor | Hex Color | Info message color | #17a2b8 |
Example Request
curl -X POST "https://api.sign.stewart.com/iframe-request" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"type": "esign",
"style": {
"primaryColor": "#006837",
"secondaryColor": "#f5f5f5",
"fontType": "Arial, sans-serif",
"textColor": "#333333",
"background": "#ffffff",
"successColor": "#28a745",
"errorColor": "#dc3545",
"infoColor": "#17a2b8"
},
"data": {
"esignId": "357aa7c7-16fd-4a2c-bd58-23da1f76fdd5",
"participantIds": [
"37da192e-6420-4b9c-9951-a979eeaf8889"
]
}
}'
Example Response
{
"url": "https://enlapp.page.link/c7u1E2jiYtCs65KCA"
}
- Extract colors from your existing brand guidelines
- Ensure sufficient color contrast for accessibility (WCAG 2.1 compliance)
Step 4: Embed the iFrame in Your Application
Now that you have the iframe URL, you can embed it in your application.
Basic HTML Example
Here's a simple HTML page that embeds the signing experience:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sign Your Document</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background-color: #f5f5f5;
}
.header {
background-color: #006837;
color: white;
padding: 20px;
text-align: center;
}
.iframe-container {
width: 100%;
max-width: 1200px;
margin: 20px auto;
background: white;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
border-radius: 8px;
overflow: hidden;
}
#signing-iframe {
border: none;
width: 100%;
height: 800px;
display: block;
}
</style>
</head>
<body>
<div class="header">
<h1>Complete Your Document Signature</h1>
</div>
<div class="iframe-container">
<iframe
id="signing-iframe"
src="https://enlapp.page.link/c7u1E2jiYtCs65KCA"
allow="camera *; microphone *"
allowfullscreen>
</iframe>
</div>
</body>
</html>
Important iFrame Attributes
| Attribute | Purpose | Required |
|---|---|---|
allow="camera *; microphone *" | Enables camera/microphone access for identity verification (if configured) | Recommended |
allowfullscreen | Allows the iframe to enter fullscreen mode | Recommended |
style="border: none" | Removes default iframe border for seamless integration | Optional |
Monitoring Signing Completion
Set up a webhook endpoint to receive real-time notifications when signing is complete.
Example esign-completed webhook payload:
{
"event": "esign-completed",
"entity": "esign",
"data": {
"notificationId": "a8b9c7d6-e5f4-3210-9876-543210fedcba",
"entity_id": "357aa7c7-16fd-4a2c-bd58-23da1f76fdd5",
"transaction_id": "transaction-uuid-here"
}
}
Key fields:
event: Always"esign-completed"for completed eSign sessionsentity: Always"esign"for eSign eventsdata.notificationId: Unique ID for this webhook notification (use for idempotency)data.entity_id: The eSignId from your transactiondata.transaction_id: The transaction ID
For webhook setup details and all available events, see Webhook Events.
The iFrame also publishes UX events to the parent frame which can be utilized for custom actions. Reach out to support for more details on available iframe events.
Best Practices
Security
- Generate iframe URLs server-side and pass only the URL to your frontend
- Validate participant access before generating iframe URLs
- Use HTTPS only for all communication
- Implement session timeouts for added security
User Experience
- Show loading states while the iframe is loading
- Provide clear instructions before displaying the iframe
- Handle errors gracefully with user-friendly messages
Troubleshooting
Common Issues and Solutions
Camera/Microphone Permissions Not Working
Issue: User can't access camera or microphone for identity verification.
Solution: Ensure the allow attribute is properly set:
<iframe allow="camera *; microphone *" ...></iframe>
Also verify your page is served over HTTPS, as camera/microphone access requires a secure context.
iFrame Not Loading
Possible causes and solutions:
Invalid or expired URL
- Generate a fresh iframe URL
- Check that the esignId and participantIds are correct
CORS or security errors
- Verify your page is served over HTTPS
- Check browser console for specific error messages
Incorrect iframe attributes
- Ensure
srcattribute is set correctly - Verify no ad blockers are interfering
- Ensure
Custom Styling Not Applied
Issue: Colors or fonts don't appear as expected.
Solutions:
- Verify hex color format is correct (e.g.,
#006837not006837) - Check that the style object was included in the iframe request
// ❌ Incorrect
{
"style": {
"primaryColor": "006837" // Missing #
}
}
// ✅ Correct
{
"style": {
"primaryColor": "#006837"
}
}
Participant Cannot Access Signing
Issue: Signer sees an error when accessing the iframe.
Possible causes:
- Participant ID doesn't match the transaction
- Transaction status is already completed or cancelled
- Transaction was deleted or expired
Solution: Verify the transaction details:
curl -X GET "https://api.sign.stewart.com/transactions/{transactionId}" \
-H "Authorization: Bearer <token>"
Related Documentation
- Create Your First eSignature Transaction - Core concepts and transaction creation
- eSign Tags Reference - Complete guide to all tag types
- Webhook Events - Real-time event notifications
- Create and Use Markup Room - Visual tag editor alternative
💬 Need Help?
Contact the Stewart Sign Support Team for technical assistance or integration guidance.