Skip to main content

Embedded components

Embedded sender widget

Embed Inkfree's four-step sender widget inside your web app: upload files, assign signers, place signature fields with drag-and-drop, and send envelopes.

Last updated:

On this page

Overview

The embedded sender widget puts Inkfree's complete document preparation flow inside an iframe on your site. Users can upload agreements, configure signers, place required signature and input fields with visual drag-and-drop, customize email copy, and dispatch envelopes without ever creating or logging into an Inkfree account.

Your server makes two API calls: POST /api/v1/inkfree/embed/drafts creates a draft, and POST /api/v1/inkfree/embed/sessions mints the one-time token. Your page then mounts the widget with that token. Before you start, read the overview to create an API key and register your origin.

Create a draft

POST/api/v1/inkfree/embed/drafts

Create a Draft for the embedded sender widget

Requires the X-API-Key header

Multipart request structure

Part / HeaderTypeRequiredDescription
requestText (JSON)RequiredThe draft settings as a JSON string (see the table below). Send it as a plain text part, not as a file.
filesFile (repeatable)OptionalOne or more documents. Repeat the part for each file. Accepted types match the sender widget's upload box (PDF, Word, Excel, text and common image files); other types are converted to PDF. If omitted, the user uploads documents in Step 1 of the sender widget.
X-Idempotency-KeyHeaderOptionalUnique idempotency key to prevent accidental duplicate draft creation upon network retries.

JSON 'request' body schema

FieldTypeDescription
emailSubjectstringDefault email subject, up to 100 characters. May be empty at this point; the user can change it in Step 4, and a subject is required when the draft is sent.
emailMessagestringDefault message body, up to 1000 characters.
expirationDaysintegerRequired. Days until the envelope expires, at least 1. There is no default, so always send it (the examples use 30).
signersarrayOptional pre-filled signers. Use [] to let the user add them in the sender widget. Each signer has id, name, email, deliveryMode ("EMBEDDED" or "EMAIL") and optionally cc. An EMAIL signer may also carry phone, deliveryChannels (["EMAIL"], ["SMS"] or both), requestSecurity (access code, one-time code or phone verification), order and a signing delay (delayDays, delayHours). The user can change all of this in Step 2.
filesarrayOptional field pre-placement. Each entry names a file with unsignedPdf and lists its fields. The name is matched to an uploaded file by its file name.
signerOrderRequired, needReminders, reminders, signRequestConfig, approvaloptionalPre-fill what the user would otherwise set in the widget: a signing order, the signer permissions (allowDocumentDownload, sendNotificationOnCompletion, attachDocumentToMailOnCompletion, all true by default) and approvers (approval.approvalNeeded, orderNeeded, reviewers[] with name and email; every approver is made EMBEDDED). The same shape the envelope endpoints return. These can still be changed in Steps 2 and 4. Automatic reminders (needReminders, reminders) and allowSignatureDelegation are not shown in the widget: a value you pre-fill is kept (when the account's plan includes the feature), and it only affects EMAIL signers, because embedded signers get no reminder emails and cannot delegate.
  • Files and signers are optional: Provide them to pre-fill the draft, or leave them out (empty signers: [] and no files part) so your user uploads documents and configures signers in the sender widget. A draft cannot be sent without at least one document and one signer.
  • Validation at creation: A subject longer than 100 characters, a message longer than 1000 characters, expirationDays below 1, an invalid signer email or duplicate signer ids are refused with 400 VALIDATION_FAILED. An empty subject is accepted now and checked when the draft is sent.
  • Embedded signer rules: An EMBEDDED signer needs a valid email, cannot be a CC recipient, and cannot be sent a link by SMS (Inkfree sends an embedded signer nothing). An access code or a one-time code is allowed. A breach returns 406 with a message that starts Exception submitting embedded sign request. Reason ::. Every approver on a draft is made EMBEDDED and needs a valid email; a pre-filled approver's email is checked when the draft is sent, and the widget shows it as VALIDATION_FAILED.
  • Pre-placed fields: Add fields with "files": [{ "unsignedPdf": "contract.pdf", "fields": [...] }] inside request. Each field's signerIndex must point at one of the draft's signers, otherwise the request is refused with VALIDATION_FAILED.
  • Signer ids: Signer id values must be unique. Inkfree renumbers them to their position in the list (0, 1, 2, ...) and updates the signerIndex of your pre-placed fields to match, so you may start from 0 or from 1.
  • Idempotency: X-Idempotency-Key makes a retry safe. Repeating a request with the same key and the same body (the JSON and the files) returns the original draft id instead of creating another draft.

Pre-placed field format

Each entry in fields is one box on a page. These are the properties you need:

  • type: one of signature, initials, name, email, text, date_signed, date, checkbox, radio_button, drop_down, company_name, title, attachment, button. Write it in lower case exactly as shown.
  • signerIndex: the id of the signer who fills the box. It must be the id of a signer in the same request. -1 is not accepted here.
  • page: the page number, counted from 0. The first page is 0.
  • x, y, w, h: the position and size in PDF points (72 points = 1 inch). x is the distance from the left edge. y is the distance from the top edge to the top of the box. A US Letter page is 612 by 792 points.

Optional properties include name (Inkfree creates a unique one if you leave it out), required, readOnly, label, placeholder, value, listItems (for drop_down), groupId (for radio_button), maxLength, minLength and multiLine. You cannot set a value on signature, initials, date_signed, attachment or button fields.

request part with pre-placed fields
{
  "emailSubject": "Vendor Agreement",
  "signers": [
    { "id": 0, "name": "Ana Ruiz", "email": "ana@example.com", "deliveryMode": "EMBEDDED" }
  ],
  "files": [
    {
      "unsignedPdf": "contract.pdf",
      "fields": [
        { "type": "signature", "signerIndex": 0, "page": 0, "x": 72, "y": 650, "w": 160, "h": 40, "required": true },
        { "type": "date_signed", "signerIndex": 0, "page": 0, "x": 260, "y": 650, "w": 110, "h": 24 }
      ]
    }
  ]
}

Upload the document in the files part with the same file name as unsignedPdf (here contract.pdf). If no uploaded file has that name, the fields are ignored without an error. The pre-placed fields appear in the field editor step of the widget.

Example curl command

curl multipart draft creation
curl -X POST "https://services.softsages.com/core/api/v1/inkfree/embed/drafts" \
  -H "X-API-Key: sk_live_YOUR_API_KEY" \
  -H "X-Idempotency-Key: YOUR_IDEMPOTENCY_KEY" \
  -F 'request={"emailSubject":"Vendor Agreement","emailMessage":"Please review and sign.","expirationDays":30,"signers":[{"id":0,"name":"Ana Ruiz","email":"ana@example.com","deliveryMode":"EMBEDDED"}]}' \
  -F 'files=@contract.pdf'

Responses

200Draft created (returns draft ID)
200 response
{
  "message": "c8a49c661ef54659b922097e3f89bf91",
  "code": 200,
  "correlationId": "01a1353b-cd8f-78ba-b868-d4e7246a9731"
}

The draft id is in message. Use it as requestId when you mint a token.

400A setting is invalid, for example VALIDATION_FAILED: emailSubject cannot exceed 100 characters.
401Missing, invalid, revoked or expired API key.
406An embedded signer breaks a signer rule, or a delivery mode is not allowed.

Mint a creation token

POST/api/v1/inkfree/embed/sessions

Mint a one-time token for the sender widget

Requires the X-API-Key header

Request body

FieldTypeRequiredDescription
scopestringRequiredMust be "creation" for the sender widget.
requestIdstringRequiredThe draft id returned by POST /api/v1/inkfree/embed/drafts. The request must still be a draft.
parentOriginstringRequiredThe origin of the page that will show the widget, registered under Settings > API Keys > Embedded signing origins (for example https://app.example.com).

Example curl command

curl mint creation token
curl -X POST "https://services.softsages.com/core/api/v1/inkfree/embed/sessions" \
  -H "X-API-Key: sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "creation",
    "requestId": "c8a49c661ef54659b922097e3f89bf91",
    "parentOrigin": "https://app.example.com"
  }'

Responses

200One-time token minted (valid for 300 seconds)
200 response
{
  "token": "YOUR_ONE_TIME_TOKEN",
  "scope": "creation",
  "requestId": "c8a49c661ef54659b922097e3f89bf91",
  "expiresInSeconds": 300
}

The token is returned only here and is not stored in readable form, so pass it straight to your page. It works once and expires after 300 seconds.

400Missing requestId, an unknown scope, or the request is not a draft (REQUEST_COMPLETED, REQUEST_VOIDED, REQUEST_EXPIRED, REQUEST_DECLINED, REQUEST_NOT_READY).
401Missing, invalid, revoked or expired API key.
403ORIGIN_NOT_REGISTERED: parentOrigin is not registered for your account. A 403 is also returned if your account is scheduled for deletion.
404REQUEST_NOT_FOUND: no draft with that id in your account.

Mounting in the frontend

Pass the minted token to your web page and call InkfreeEmbed.mount() with type: "create":

Mount the sender widget
<div id="sender-widget" style="width: 100%; height: 850px;"></div>

<script src="https://sign.inkfree.app/embed/inkfree-embed.js"></script>
<script>
  var widget = InkfreeEmbed.mount({
    container: "#sender-widget",
    type: "create",
    token: token,
    minHeight: "820px",
    title: "Document Preparation"
  });

  widget.on("send_completed", function (event) {
    console.log("Envelope dispatched:", event.requestId);
    // Redirect or update parent UI
  });
</script>

The four steps walkthrough

StepWhat your user can doValidation before moving forward
1. Upload DocumentAdd files by drag and drop or the file browser, and remove files. Each file is stored on the draft as soon as it uploads.At least one document. Up to 10 MB per file. A duplicate file name is refused. The upload box shows how many documents the draft may hold.
2. Approvers and SignersAdd signers and CC recipients, set each one to Need to sign or Receives a copy, turn on a signing order with levels, and give a signer a signing delay (days and hours) before their turn. A security option for each signer: none, one-time code by email, one-time code by text, an access code you share, or identity verification where a vendor is configured. For a signer Inkfree emails (a pre-filled EMAIL signer) there is also a phone number and delivery by email and/or text (SMS). On the Approvers tab: approvers and approver groups who must approve before the signers are invited, in order or all at once. Approvers approve inside your app, like embedded signers; Inkfree emails them nothing. In-person signing is not offered.At least one signer who is not a CC recipient; emails must be unique. A signer reached by text only may leave the email blank. Choosing text delivery asks the user to confirm the recipients agreed to be texted (SMS consent) before leaving the step. Options the account's plan does not include are hidden or refused at send with VALIDATION_FAILED.
3. Sign Request EditorDrag fields from the left panel onto the document pages for each signer: Signature, Initials, Date, Text, Checkbox and more, plus the account's custom fields. Auto-place offers the fields Inkfree's AI detected in the document. The right rail has the AI Assistant (ask questions about the documents) and AI Insights (summary and contract at a glance) when the plan includes the AI assistant.Every signer who is not a CC recipient needs at least one field.
4. Email configurationsSet the email subject and message, the expiry in days (when the plan includes it), the signer permissions (download the documents, completion notification, attach the signed copies to the completion email), and schedule the send for a later date and time. The live email preview uses the account's branding (logo, colours, footer).A subject is required, up to 100 characters. A scheduled time must be in the future.

Step validation & save semantics

Next checks the current step before moving on. Clicking a later step in the step bar checks every step before it. Back keeps what the user entered. Documents are saved to the draft as soon as they upload. Signers, fields and email settings are saved only when the user clicks Send, and the server checks everything again at that moment. If a check fails, the widget shows the message inline and sends an error event with VALIDATION_FAILED (recoverable). When the send succeeds, the widget sends send_completed and shows a confirmation panel.

Signers and delivery modes

  • Signers added in the widget: They sign in your app (deliveryMode: "EMBEDDED"). Inkfree sends them no email or text: you mint a signing token for each of them when it is their turn and open the signing widget yourself. The user cannot change this inside the widget.
  • Pre-filled signers: A signer you passed in the draft request keeps the mode you gave it (EMBEDDED or EMAIL; a signer with no mode counts as EMAIL), matched by email address. If the user changes a pre-filled signer's email in the widget, Inkfree treats it as a new signer, who signs in your app.
  • Embedded signers: They need a valid email and cannot be CC recipients. The user can protect them with an access code, a one-time code by email or a one-time code by text (or identity verification where it is set up); the signer is asked for it inside your iframe before the document opens. There is no "Deliver via" choice for them, because Inkfree sends them nothing, and they cannot be sent a link by SMS. On the signing widget they cannot delegate, and they can download the documents unless the sender switched off "Download documents" in Step 4.
  • Email signers: They get the account's normal invitation, reminders and completion email. Their Inkfree signing link is the signer's url in GET /api/v1/inkfree/envelopes/{id}; minting a signing token for them fails with SIGNER_NOT_EMBEDDED.
  • Approvers: Every approver on a draft is EMBEDDED. Inkfree sends them nothing; you open the signing widget for them with a token minted for their email, and they approve or reject inside your app (see Embedded approvers). The envelope response lists them under approval.reviewers with their status and deliveryMode, and no url.
  • CC recipients: A CC recipient always receives the final copy by email.

After the draft is sent

Sending turns the draft into an envelope with the same id. The send_completed event carries the envelope's status in data.status, and your page should act on it:

  • Pending: the signers are up. Read GET /api/v1/inkfree/envelopes/{id}, and for each EMBEDDED signer with status Pending mint a signing token and mount the signing widget when they are ready to sign. With a signing order, a signer whose turn has not come gets NOT_YOUR_TURN from the mint call; show them as waiting and try again after the earlier signers have signed (the signer.signed webhook tells you when). See Embedded signing.
  • InReview: the user added approvers. For each approver with status Pending, mint a signing token with the approver's email and mount the signing widget; they approve or reject there (with an approval order, only the current approver gets a token, others get NOT_YOUR_TURN). The status becomes Pending once they have all approved, or Rejected if one rejects. There is no webhook for approval: use the widget's approval_completed and approval_rejected events as a hint and confirm by polling the envelope. A token for a signer before then fails with REQUEST_NOT_READY.
  • Scheduled: the user scheduled the send. The envelope's scheduleTime says when it goes out and becomes Pending (or InReview first, with approvers). Poll after that time; minting earlier fails with REQUEST_NOT_READY.

The widget stays on its confirmation panel until your page removes it with widget.destroy(). The envelope response also carries signRequestConfig (the permissions the user chose) and each signer's and approver's deliveryMode, status and, for email signers, url.

Omitted features

These features are deliberately excluded from the sender widget: in-person signing, saved templates ("Choose Template"), cloud drive imports, the eSign-mode choice, and creating or editing custom fields (the account's existing custom fields can be placed). Everything else in Inkfree's own four-step wizard is available, subject to the account's plan: approvers (who approve inside your app), signing delays, SMS delivery, one-time codes and access codes, identity verification, signer permissions, scheduled sends, AI field detection, the AI assistant and AI insights.