Back to Blog
eSignatureEmbedded SigningAPIDevelopers

How to Embed Digital Signing in Your App (Complete Developer Guide)

PDFSignify TeamMarch 15, 202611 min read

If you're building a SaaS product, internal tool, or any application that handles contracts and documents, you want the signing experience to feel native. Users shouldn't be redirected to an external service, and the signing should feel like a built-in feature of your product — not a third-party bolt-on.

This guide shows how to embed digital signing directly into your application using the PDFSignify API. Unlike eSignature platforms that rely on iframes and hosted signing pages, PDFSignify is a backend API that gives you full control over the user experience.

What "Embedded Signing" Means with PDFSignify

Traditional eSignature platforms use an embedded iframe model: your backend requests a signing URL, and your frontend loads that URL in an iframe or redirects the user. The signing UI belongs to the third party.

PDFSignify works differently. It's a certificate-based PDF signing API. You send a PDF and a digital certificate (.pfx/.p12) to the API, and you get back a cryptographically signed PDF. There's no hosted signing UI, no iframe, and no redirect. "Embedding" the signing means building the feature into your own backend and designing whatever UI you want on the frontend.

Why This Approach Is Better for Developers

  • Full control over your UI — design the signing flow exactly as you want it
  • No third-party branding or hosted pages
  • Synchronous API — send a file, get a signed file back, no polling or webhooks
  • No dependency on external signing sessions or tokens that expire
  • Your users never leave your application
  • Simpler architecture with fewer moving parts

The Architecture

The embedded signing flow has three parts: your frontend collects the file, your backend signs it via PDFSignify, and the result comes back to the user.

  • Frontend: file upload form, progress indicator, download button
  • Backend: receives the PDF, calls PDFSignify's sign-pdf endpoint with the certificate, returns the signed PDF
  • PDFSignify API: handles the cryptographic signing and returns the result immediately

Step 1: Backend Signing Endpoint (Node.js)

Your backend is the only component that communicates with PDFSignify. It holds the certificate and API keys, and exposes a simple endpoint that your frontend can call.

javascript
const express = require("express");
const multer = require("multer");
const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");

const app = express();
const upload = multer({ dest: "uploads/" });

app.post("/api/sign-document", upload.single("pdf"), async (req, res) => {
  const formData = new FormData();

  formData.append("pdf", fs.createReadStream(req.file.path), {
    filename: "document.pdf",
    contentType: "application/pdf",
  });
  formData.append(
    "certificate",
    fs.createReadStream("./certificates/company.pfx"),
    { filename: "certificate.pfx", contentType: "application/x-pkcs12" }
  );
  formData.append("certificatePassword", process.env.CERT_PASSWORD);
  formData.append("signaturePageAppearance", "-1");
  formData.append("signatureMessage", "Digitally signed by MyApp");
  formData.append("signatureHeight", "100");
  formData.append("signatureWidth", "200");
  formData.append("signatureXPosition", "150");
  formData.append("signatureYPosition", "80");

  try {
    const response = await axios.post(
      "https://api.pdfsignify.com/api/v1/sign-pdf",
      formData,
      {
        headers: {
          ...formData.getHeaders(),
          AccessKey: process.env.PDFSIGNIFY_ACCESS_KEY,
          SecretKey: process.env.PDFSIGNIFY_SECRET_KEY,
        },
        responseType: "arraybuffer",
      }
    );

    fs.unlinkSync(req.file.path);

    res.setHeader("Content-Type", "application/pdf");
    res.setHeader(
      "Content-Disposition",
      'attachment; filename="signed.pdf"'
    );
    res.send(Buffer.from(response.data));
  } catch (error) {
    fs.unlinkSync(req.file.path);
    res.status(500).json({ error: "Signing failed" });
  }
});

Step 2: Backend Signing Endpoint (Python/Flask)

Here's the same endpoint in Python with Flask, showing that the pattern works in any language.

python
import requests
from flask import Flask, request, send_file
import tempfile
import os

app = Flask(__name__)

@app.route("/api/sign-document", methods=["POST"])
def sign_document():
    pdf_file = request.files["pdf"]
    pdf_path = os.path.join(tempfile.gettempdir(), pdf_file.filename)
    pdf_file.save(pdf_path)

    response = requests.post(
        "https://api.pdfsignify.com/api/v1/sign-pdf",
        headers={
            "AccessKey": os.environ["PDFSIGNIFY_ACCESS_KEY"],
            "SecretKey": os.environ["PDFSIGNIFY_SECRET_KEY"],
        },
        files={
            "pdf": ("document.pdf", open(pdf_path, "rb"), "application/pdf"),
            "certificate": (
                "cert.pfx",
                open("certificates/company.pfx", "rb"),
                "application/x-pkcs12",
            ),
        },
        data={
            "certificatePassword": os.environ["CERT_PASSWORD"],
            "signaturePageAppearance": "-1",
            "signatureMessage": "Digitally signed by MyApp",
            "signatureHeight": "100",
            "signatureWidth": "200",
            "signatureXPosition": "150",
            "signatureYPosition": "80",
        },
    )

    os.remove(pdf_path)

    if response.status_code != 200:
        return {"error": "Signing failed"}, 500

    signed_path = os.path.join(tempfile.gettempdir(), "signed.pdf")
    with open(signed_path, "wb") as f:
        f.write(response.content)

    return send_file(signed_path, as_attachment=True, download_name="signed.pdf")

Step 3: Frontend Integration

Your frontend doesn't need any special SDK or widget. It's a standard file upload that sends the PDF to your own backend and receives the signed version back.

javascript
async function signDocument(pdfFile) {
  const formData = new FormData();
  formData.append("pdf", pdfFile);

  const response = await fetch("/api/sign-document", {
    method: "POST",
    body: formData,
  });

  if (!response.ok) {
    throw new Error("Signing failed");
  }

  const blob = await response.blob();
  const url = URL.createObjectURL(blob);

  const link = document.createElement("a");
  link.href = url;
  link.download = "signed_document.pdf";
  link.click();

  URL.revokeObjectURL(url);
}

This function works with any framework — React, Vue, Svelte, or plain HTML. It sends the file to your backend, gets back the signed PDF as a blob, and triggers a download.

Real-World Embedding Patterns

Pattern 1: Sign on Upload

Automatically sign every PDF that's uploaded to your system. Useful for document management platforms that need every file certified on ingestion.

javascript
app.post("/api/upload", upload.single("document"), async (req, res) => {
  const signedPdf = await signWithPdfSignify(req.file.path);

  await saveToStorage("signed/" + req.file.originalname, signedPdf);

  fs.unlinkSync(req.file.path);

  res.json({ message: "Document uploaded and signed", status: "success" });
});

Pattern 2: Sign on Approval

When a document goes through an approval workflow, sign it only after the final approval step. Your backend triggers the signing when the business logic allows it.

javascript
app.post("/api/documents/:id/approve", async (req, res) => {
  const document = await db.documents.findById(req.params.id);

  if (document.status !== "pending_approval") {
    return res.status(400).json({ error: "Document not in approval state" });
  }

  const signedPdf = await signWithPdfSignify(document.filePath);

  await saveToStorage(document.signedPath, signedPdf);
  await db.documents.update(req.params.id, {
    status: "signed",
    signedAt: new Date(),
    signedBy: req.user.id,
  });

  res.json({ message: "Document approved and signed" });
});

Pattern 3: Batch Signing

Sign multiple documents in a loop — for example, end-of-month invoice batches. Since PDFSignify's API is stateless, each call is independent.

javascript
async function signBatch(pdfPaths) {
  const results = [];

  for (const pdfPath of pdfPaths) {
    try {
      const signed = await signWithPdfSignify(pdfPath);
      results.push({ path: pdfPath, status: "signed", data: signed });
    } catch (err) {
      results.push({ path: pdfPath, status: "failed", error: err.message });
    }
  }

  return results;
}

Comparison: PDFSignify vs. Iframe-Based Signing

  • Iframe approach: Third party controls the signing UI. You depend on their session tokens, redirect URLs, and webhook callbacks. The signing UI can look foreign to your users.
  • PDFSignify approach: You control everything. Your backend calls the API, your frontend shows whatever UI you design. The signing is invisible to the user — they just see your app.

When to Use Each Approach

If you need a click-to-sign workflow where a human draws a signature on screen, you need an eSignature platform with a UI component. If you need to apply a cryptographic digital signature to PDFs using a certificate (for compliance, legal validity, or document integrity), PDFSignify is the right tool. Many applications use both — an eSignature UI for the human interaction, then PDFSignify to certify the final document.

Security Considerations

  • Never expose your AccessKey, SecretKey, or certificate to the frontend
  • Always authenticate users before allowing them to trigger signing
  • Clean up temporary files after every request
  • Store signed PDFs in secure storage with access controls
  • Log every signing operation for audit purposes

Why Developers Prefer This Model

PDFSignify gives you a clean API that does one thing: sign PDFs with certificates. There are no signing sessions to manage, no webhook endpoints to maintain, no document states to track, and no callback URLs to configure. This means less code, fewer failure points, and a signing feature that's as reliable as any other API call in your application.

True embedded signing means your users never know there's an external API involved. With PDFSignify, the signing is just another feature of your app.