Skip to main content

Sending a signing request

This guide covers creating a signing request, attaching a template or document, and inviting recipients to sign.

Create vs. create-and-send

POST /signing-requests creates a draft only - it never sends an email, no matter what settings you pass. To notify recipients immediately, use POST /signing-requests/create-and-send instead, or call .../send on the draft afterward. This is the most common cause of “I created a signing request but nothing was sent” reports.
Firma exposes two ways to start a signing request, and picking the wrong one is the most common integration mistake: Use create when your workflow needs a review or editing step before anything reaches a recipient. Use create-and-send when you want the request live and recipients notified in a single call.

The send_signing_email flag

This flag lives in settings.send_signing_email, but it means something different depending on which endpoint you call:
send_signing_email: false on create-and-send is not a silent draft - it’s a fully sent, billed signing request with no email attached. Use it when you plan to deliver the signing link yourself (embedding it, or sending your own notification). If you want something you can still cancel or edit before it becomes final, use create (the draft endpoint) instead.

The allow_presigning_download flag

Controls whether recipients can download the unsigned document before completing their part of the signing flow. It behaves the same on both endpoints:
  • If you set it explicitly in settings, that value is stored on the signing request.
  • If you omit it, it resolves at view/download time through an inheritance chain: signing request → workspace → company setting, defaulting to disallowed if none of those are set.
  • When creating from a template and omitting it, the request inherits the template’s own allow_presigning_download value.
The public OpenAPI schema for create-and-send doesn’t currently list allow_presigning_download under its settings object, but the endpoint accepts and applies it identically to POST /signing-requests.

Steps

  1. Create or select a template
  2. Create a signing request referencing the template
  3. Add recipients with required information (first name, last name, email)
  4. Optionally add form fields with percentage-based positioning
  5. Send the request via email or embed the signing view

Recipient Schema (Required Fields)

Recipients require first_name and last_name as separate fields - there is no single name field.
Each recipient must include:
  • first_name (required) - Recipient’s first name
  • last_name (optional) - Recipient’s last name (required only when creating via POST /signing-requests with a raw document)
  • email (required) - Email address (create warns on invalid format; create-and-send and /send reject it)
  • designation (required) - Role: "Signer", "CC", or "Approver". Approvers review and approve the document (no signature) via the approval_* field types below
  • order (optional) - Signing order for sequential workflows
Optional fields:
  • phone_number, street_address, city, state_province, postal_code, country, title, company
  • custom_fields - Object with custom key-value pairs

Create a signing request from a template (API)

Endpoint: POST /signing-requests
Example curl (create request from template):
Successful response (201) returns a Document resource including id (the signing_request_id) and document_url where appropriate.

Create a signing request (server example) - Node (fetch)

Create a signing request (server example) - Python (requests)

Create a signing request from a document

Instead of using a template, you can create a signing request by uploading a PDF or DOCX document directly. Choose the method based on your file size:
Inline base64 (document) works for small files, but sending a large document this way can fail with a 502 before your request ever reaches application validation - the payload hits a platform-level size limit, not an error you can catch and retry cleanly. If a document is anywhere near 5MB, use the two-step upload flow (document_id) below instead of inline base64, even though it’s more code to write.
For documents under 5MB, include the base64-encoded file directly in the request body:
You must provide exactly one of document, document_id, or template_id. They are mutually exclusive.

Adding form fields (percentage-based positioning)

Critical: All field position coordinates (x, y, width, height) must be percentages (0-100) relative to page dimensions, not pixels. The page_number field is required.
Want a field to show a value before the signer touches it - a fixed value you already know, or the recipient’s own profile data? See the Field Prefilling guide. variable_name alone does not do this.
When creating a signing request directly (POST /signing-requests) or updating one, you can add form fields:

Field positioning example

Field types

  • signature - Signature field
  • text - Single-line text input
  • date - Date picker
  • checkbox - Checkbox
  • dropdown - Dropdown selector (requires dropdown_options)
  • initial - Initials field (also accepts initials as an alias)
  • approval_signature - APPROVED stamp (Approver only)
  • approval_checkmark - Approval checkmark (Approver only)
  • approval_date - Approval date (Approver only)
The approval_* field types can only be assigned to a recipient whose designation is "Approver" (assigning one to a Signer returns a 400). Their value is authored server-side when the approver completes their review, so you don’t submit a value for them, and the approval stamp is rendered onto the completion certificate.

Positioning guidelines

The coordinate system uses percentages for responsive scaling:
  • x: 0 (left edge) to 100 (right edge)
  • y: 0 (top edge) to 100 (bottom edge)
  • width: percentage of page width (e.g., 30 = 30% width)
  • height: percentage of page height (e.g., 8 = 8% height)
For a US Letter page (8.5” × 11”), use these rough conversions:
  • 1 inch ≈ 11.76% width
  • 1 inch ≈ 9.09% height

Updating signing requests

Before a signing request is sent, you can update its details using the API. The API provides two methods:
Cannot update after sending: Once a signing request is sent, it cannot be modified. Updates only work for requests with status not_sent.

Comprehensive update (PUT)

Use comprehensive-update-signing-request for complex updates involving multiple sections. When to use:
  • Updating multiple recipients at once
  • Deleting recipients (with field reassignment/deletion)
  • Updating fields and reminders together
  • Making coordinated changes across multiple sections
Structure: All sections are optional, but at least one must be provided:
  • signing_request_properties - Update name, description, document, expiration, settings
  • recipients - Upsert recipients (include id to update, omit to create)
  • deleted_recipients - Delete recipients with field_action (delete or reassign fields)
  • fields - Upsert fields (include id to update, omit to create)
  • reminders - Upsert reminders (include id to update, omit to create)
Requirements:
  • ✅ Can update multiple sections in one request
  • ✅ Supports recipient deletion with field handling
  • ✅ Only works before the request is sent
Example (Node.js):

Partial update (PATCH)

Use partially-update-signing-request when updating specific properties or a single recipient. When to use:
  • Updating name, description, or settings
  • Adding or updating one recipient at a time
  • Making targeted changes without affecting other data
Important: Cannot update both properties AND a recipient in the same request. Choose one:
  • Update properties only (name, description, document, expiration_hours, settings)
  • OR update/create a single recipient
Benefits:
  • ✅ Only send the fields you want to change
  • ✅ More efficient for small changes
  • ✅ Other fields remain unchanged
  • ✅ Safer for concurrent edits
Example (Node.js):
Example (Python):

Choosing between PUT and PATCH

Important: Both update methods only work before the signing request is sent. Once sent, the signing request becomes immutable to prevent tampering with active signature workflows.
Best practices:
  • Update signing requests before calling /send
  • Validate recipient data before updating
  • Use PATCH for incremental changes
  • Implement retry logic with exponential backoff

Sending (email invites)

Once you have a signing request ID (and have made any necessary updates), call POST /signing-requests/{signing_request_id}/send to send emails to all recipients.

Example

The /send endpoint validates that all recipients have required information (first_name and email - last_name is optional) and that any prefilled fields have the corresponding recipient data present.

Embedding the signing view

To embed the signing experience in your own app, fetch the recipient’s id from GET /signing-requests/{id}/users and build the signing URL:
Render this URL in an iframe. For the complete embed setup - including postMessage events, iframe sizing, and camera/clipboard permissions - see the Embeddable Signing guide.

Edge cases & tips

  • Signing order: Ensure recipients have sequential order values (1, 2, 3…) for sequential signing workflows
  • Audit trail: Download the audit trail via GET /signing-requests/{id}/tracking to see all user actions
  • Download completed PDF: Use GET /signing-requests/{id}/download after completion
  • Webhooks: Subscribe to events like signing_request.completed instead of polling (see Webhooks guide)

Next steps

  • For sequential signing workflows with multiple signers, ensure each recipient has a sequential order value (1, 2, 3…).
  • For audit and compliance, download the final PDF via GET /signing-requests/signing_request_id/download after completion.
  • Use webhooks (see Webhooks Guide) to react to signing events instead of polling.