letssign.now docs

Placement modes

Where signature fields land on the PDF — anchors, auto-append, explicit, manual. Visualised, with when-to-use guidance.

Pick a mode with the placement form field on POST /v1/signing-requests. The default is anchors with a fall-through to auto_append when no markers are found. Four modes total, no fifth.

There is no separate "magic-link" mode. An earlier draft of this API had placement_link_mode: "login_required" | "magic" as a parameter on manual mode. It was collapsed before launchmanual now handles both paths under a single URL: if the visitor is signed into the matching workspace, the audit trail records their user_id; otherwise the high-entropy single-use token in the URL doubles as the credential. Same effective security, simpler contract.

At a glance

ModeWhen to pick itCaller passes coordinates?Field placement happens at
anchorsYou generated the PDF programmatically (HTML→PDF, LaTeX, Word) with markers.NoAPI call time
auto_appendAd-hoc letters, no structure, just need a signature page on the end.NoAPI call time
explicitYou generated the PDF programmatically AND tracked field positions yourself.YesAPI call time
manualA human places fields after upload — paralegal review, external counsel.No (deferred)When the placer hits Send

anchors (default)

Drop a marker like [[ls:signature:tenant]] in your PDF (HTML→PDF, LaTeX, Word, anywhere with a real text layer). We find it, mask the marker with a white rectangle, and place the signature field on top.

1 — UPLOAD
PDF with markers in text layer
Tenant signature:
[[ls:signature:tenant]]
─────────────────
2 — SCAN
pdfjs reads positions; we white-rect each marker
Markers are masked so they don't bleed through under the field.
3 — PLACE
Signature field rendered on top of the masked region
Sign here

Best ergonomics for programmatically generated contracts — HTML→PDF templates, document-assembly tools (Portant, DocAssemble), LaTeX, Pandoc. See Anchor placeholders for the full marker syntax.

Caveats:

  • The PDF's text layer must contain the marker. Scanned-image PDFs don't qualify (run them through OCR first).
  • Markers wrapped across two lines are skipped silently — keep them on one line in the source template.
  • A marker can appear once per page per role for signature / initial / date / name. Duplicates → 400 duplicate_anchor.

auto_append

We add a fresh signature page after your PDF — one block per signer, role-labelled with a signature line and a date line. No coordinates needed from you.

1 — UPLOAD
Original PDF (N pages)
2 — APPEND
We add page N+1 with role-labelled blocks
3 — SIGN
Signers sign on the appended page
TENANT
LANDLORD

Good for ad-hoc letters and quick-and-clean send-and-forget flows where there's no existing signature area. Also the fall-through when anchors mode finds zero markers in the PDF — rather than bouncing your call with no_anchors_found, we silently switch to auto_append so the document still goes out.

Caveats:

  • Adds at least one extra page (more if you have >7 signers).
  • Page size matches A4 regardless of your source PDF's size.

explicit

You pass a fields[] array with one tuple per field, in normalized [0..1] coordinates with a top-left origin:

{
  "placement": "explicit",
  "fields": [
    { "page": 0, "x": 0.10, "y": 0.85, "w": 0.30, "h": 0.06, "kind": "signature", "role": "tenant" },
    { "page": 0, "x": 0.45, "y": 0.85, "w": 0.30, "h": 0.06, "kind": "signature", "role": "landlord" },
    { "page": 0, "x": 0.10, "y": 0.92, "w": 0.15, "h": 0.03, "kind": "date",      "role": "tenant" }
  ]
}
1 — UPLOAD
PDF + JSON coords from your generator
{ "page": 0,
"x": 0.10,
"y": 0.85,
...
2 — VALIDATE
Each role must match a signer; coords clamp to [0..1]
3 — PLACE
Field rendered exactly where you said

Use when you generated the PDF programmatically AND tracked field positions at generation time — most often a templating system with inline metadata about where each field belongs.

Coordinate system:

  • Origin top-left (matches our editor; PDF native is bottom-left but you don't need to think about that).
  • Both x and y are in [0, 1] — fractions of page width / height.
  • kind is signature | initial | date | text.
  • role MUST match a signers[].role value.

Caveats:

  • No safety net — coords land where you say. A bug in your generator puts the signature box on top of the legalese.
  • Page sizes vary; if your generator outputs Letter and the field table assumes A4, fields land where they shouldn't.

manual

Returns a placementUrl instead of emailing signers immediately. The recipient — typically a paralegal, legal counsel, or account manager — opens the URL, drops fields in our editor, and hits Send. Only THEN are the signing requests created and the signers emailed.

1 — POST
PDF + signers; no field info yet
{ "placement":"manual",
"placement_assignee_email":"…" }
2 — EMAIL
Assignee gets a placement URL
Place fields →
3 — PLACE
Editor opens; placer drops fields
4 — DISPATCH
Send → signers get invites
signing_requests rows created at this step, not at the original POST.
{
  "placement":                "manual",
  "placement_assignee_email": "paralegal@yourfirm.com",
  "signers": [
    { "email": "tenant@example.com",  "role": "tenant" },
    { "email": "landlord@example.com", "role": "landlord" }
  ]
}

Response (HTTP 202):

{
  "documentId":            "8a1e4f9a-…",
  "status":                "awaiting_placement",
  "placement":             "manual",
  "placementUrl":          "https://letssign.now/place/<token>",
  "placementToken":        "abc…",
  "placementAssigneeEmail": "paralegal@yourfirm.com",
  "placementExpiresAt":    "2026-05-13T10:30:00Z",
  "signers": [
    { "role": "tenant",   "email": "tenant@example.com",  "status": "awaiting_placement" },
    { "role": "landlord", "email": "landlord@example.com", "status": "awaiting_placement" }
  ]
}

The placement link works with or without a workspace login. If the visitor is signed into the matching workspace, the audit trail records their user_id; otherwise the token in the URL is the credential and the trail records the assignee email. Same effective security as a signed-in flow — token is 32 hex characters (128 bits), single-use, document-scoped, 14-day TTL.

Useful for:

  • Legal review / paralegal placement — the API caller is your CRM trigger, the placer is a real human at your firm.
  • External counsel — outside law firm reviewing a contract on their own computer with no workspace account.
  • Agent-generated PDFs with human review — an LLM drafts the contract, a lawyer places the signature fields before send. Avoids the failure mode of an AI putting the signature box mid-paragraph.

Caveats:

  • Two-step flow — the original POST creates a placeholder, not a live signing request. Until the placer hits Send, no signer is notified and no signing_request row exists.
  • The placement token expires after 14 days (configurable via expires_in_days). After that, the document is stranded — recover by re-POSTing.
  • Status awaiting_placement is distinct in the GET /v1/documents rollup so your dashboard can show a "needs human" queue.