Open-source · self-hosted · API-first

Electronic signatures your backend drives — then deletes.

NoSign is a signing motor, not a vault. Feed it a PDF and a signer list; it runs the whole ceremony, seals the result, delivers it by signed webhook, and hard-deletes everything. The full API and hard delete are free — not a paid tier.

« No Schmarrn. Just Signatures. »

POST /v1/signing-requests
Authorization: Bearer sk_live_...
{
"document": "<base64 pdf>",
"callback_url": "https://your-app.com/webhooks/nosign",
"signers": [
{ "name": "Ada Lovelace", "email": "ada@example.com",
"fields": [{ "page": 1, "x": 72, "y": 640, "w": 180, "h": 48, "required": true }] }
]
}
201 Created
{ "id": "sr_8fk2", "status": "pending",
"signing_url": "https://nosign.app/s/aZ9...",
"expires_at": "2026-06-14T09:00:00Z" }

Why NoSign exists

The features you actually wanted shouldn't be the paid tier.

NoSign isn't the first open-source tool for electronic signatures — we're not reinventing the wheel. But where other projects are open source yet keep the genuinely useful features behind a paywall, NoSign is open source all the way down: every feature is free. No premium tier. No SaaS. Released under AGPLv3 — download it, it's yours.

What you actually wanted NoSignOthers
Full REST API Paid tier
Hard delete after delivery Rarely / paid
Self-host, no per-seat fee Limited
Signed webhook + audit bundle Paid tier
Five field types + reusable templates Paid tier
Public offline verification Rare

Why it exists

Built because nothing else quite fit.

From the maker of Wintertrace (Schneespur) — open-source ops software for winter-service crews.

NoSign started as a side-quest. I build Wintertrace — open-source software for winter-service crews that logs jobs automatically with GPS, weather, and everything a route needs. It's modular, and one module lets crews draft service contracts for their customers right inside the app, instead of paying for a separate contract tool.

The missing piece was signing. The usual dance — print the contract, mail it or meet up, sign, mail it back, file it somewhere, maybe re-scan it later — is slow and joyless. Customers should just sign, in seconds.

So I went looking for an open-source signing engine. The good ones kept letting me down: one had everything I needed, but the API turned out to be a paid add-on — on an app that calls itself open source. Another was solid, but had no real hard delete.

A contract comes in, everyone signs, it goes back to my system — and it's deleted. I don't want to hoard documents.

Rather than get burned by a fourth tool, I built NoSign with Claude Code: open source, API-first, hard delete, a properly signed PDF, and a strong audit trail. Exactly what I wanted — so it's open source for anyone with the same itch.

— Michael, maker of NoSign & Wintertrace

How it works

Sign, seal, webhook, gone.

  1. 01

    Your API posts

    PDF + signers + field coordinates. Your platform is always the gatekeeper.

  2. 02

    NoSign runs the ceremony

    Email verify → view PDF → consent → draw signature → submit. Sequential for multiple signers.

  3. 03

    Seal

    PAdES-B-T seal + embedded RFC3161 timestamp from a self-hosted TSA.

  4. 04

    Signed webhook

    Sealed PDF (base64) + ordered audit bundle, HMAC-SHA256, with retries.

  5. 05

    Erased

    On your 2xx ack, NoSign hard-deletes everything. Only a PII-scrubbed tombstone remains.

Not every request reaches the seal: a signer can decline (terminal, with an optional reason), and unsigned requests expire after a configurable window (default 30 days) — with reminder emails on a cadence (default 7 / 3 / 1 days) beforehand. Each lifecycle change fires its own webhook.

The signing ceremony

What the signer sees.

NoSign hosts the signer-facing pages directly — the only public surface. Everything else is your API.

  • 01  Verify email

    OTP or magic link before any document access.

  • 02  View the full PDF

    PDF.js viewer; the signer reads what they sign.

  • 03  Consent, verbatim

    The exact rendered checkbox wording is stored — provability over prettiness.

  • 04  Draw the signature

    Mouse or finger, mobile-friendly. A real, visible mark.

signature_pad

Ada Lovelace — signed on nosign.app

Provability

Provability is the prime directive.

Every step recorded with a UTC timestamp, an HMAC-hashed IP, actor, and document hash. The finished PDF is sealed in place (PAdES-B-T) and carries an embedded RFC3161 timestamp — readers show "signed, not modified since signing."

PAdES-B-T · self-hosted TSA · zero paid crypto deps
Signing request audit log
Timestamp Event Actor Document hash
2026-06-07T09:01:12Z request.created api_key:central sha256:7f3a…
2026-06-07T09:03:44Z signer.email_verified ip:hmac:b91c… sha256:7f3a…
2026-06-07T09:05:02Z consent.captured signer:ada sha256:7f3a…
2026-06-07T09:05:51Z signature.submitted signer:ada sha256:9c20…
2026-06-07T09:05:59Z document.sealed tsa:self sha256:9c20…

The evidence layer

And now anyone can check the proof.

Every sealed PDF carries its own evidence — an audit certificate page and a machine-readable record, both inside the signed bytes. A public portal verifies them offline, so the proof no longer depends on pre-trusting the platform that made it.

  • Audit certificate, in the document

    A bilingual (de/en) certificate page is appended before the seal — signer identity, verbatim consent, HMAC-hashed IP, document hash, and a QR code.

  • Machine-readable record, inside the seal

    A schema-versioned nosign-audit.json is embedded within the signed ByteRange — structured proof that travels inside the bytes, not bolted on beside them.

  • Checkable by anyone, offline

    A public /verify portal — a stateless fourth trust boundary with no auth, no session, no database. Upload a sealed PDF and get a verdict.

Five verdicts from /verify

  • VALID

    Seal intact, ByteRange matches, timestamp checks out.

  • TAMPERED

    Bytes changed after signing — incl. trailing-byte shadow attacks.

  • INVALID

    A seal is present but the signature or timestamp fails to validate.

  • NO_SEAL

    A PDF with no NoSign seal at all — nothing to verify.

  • INPUT_ERROR

    Not a readable PDF, or the upload could not be parsed.

The portal re-checks ByteRange integrity, validates the embedded RFC3161 timestamp, and detects trailing-byte shadow attacks — real PAdES-B-T proof made checkable by anyone, not just the platforms that already pre-trust the seal.

Privacy by erasure

Then it's gone.

Every other e-sign tool is a vault that keeps your documents — that's the lock-in. NoSign is a motor. Nothing is deleted until your backend acknowledges the webhook; a daily scheduler is the safety net. After hard delete, only a PII-scrubbed audit tombstone remains.

delete → 204 No Content

signing_request: sr_8fk2

tombstone kept · PII scrubbed

204 · erased

Everything else

The rest of the motor.

Five field types

Signature, initials, date (server-derived), checkbox, and text — each validated and stamped per type. Your platform still owns placement.

Reusable templates

Define signer slots + field positions once, versioned. Fields are snapshotted per request, so editing a template never touches requests in flight.

Sequential multi-signer

NoSign enforces the turn, re-imports the running document, emails the next signer. Final webhook fires once.

Full lifecycle

Decline (with reason), expire after a configurable window, and reminder emails on a cadence — each a terminal state with its own webhook.

Signed webhook delivery

HMAC-SHA256, exponential-backoff retries, dead-letter path — now incl. lifecycle events (signer.signed, declined, expired).

Rotation-safe webhooks

Rotate HMAC secrets with zero downtime — during the window NoSign signs with all active secrets in a multi-digest header.

Multi-service API keys

Named per source app, SHA-256-hashed (shown once), revocable, with per-request attribution.

Internationalized (de/en)

Signer UI and emails localized per signer from day one.

Isolated admin dashboard

Separate boundary with 2FA, no public registration: triage, search, audit inspection.

Self-contained

Local storage (no S3), self-hosted SMTP, self-hosted TSA. Everything in the box.

Deliberately not

Honest about what it isn't.

  • SES, not QES/AES. The seal is an organizational integrity + timestamp seal, not the signer's qualified identity.
  • Single-tenant, not SaaS. One client (your platform). No public sign-ups, no multi-tenant billing — the sandbox is opt-in, not multi-tenant.
  • No external services. No S3, no third-party timestamping. An accepted trade-off for "everything in the box."
  • Your platform owns field placement. Field types and templates ship in the box, but NoSign never parses the PDF for positions — and there's no drag-and-drop placement UI. Bad coords are rejected at ingestion (422).
  • Sequential, not parallel. Signers sign in order. Parallel multi-signing is out of scope.
  • Provable now, full LTV later. Embedded evidence + an offline verifier ship today; full PAdES-LTV and an AATL-trusted certificate are a later drop-in, no code change.

Developer experience

Integrate without touching production.

NoSign is open source — and v3.0 makes it pleasant to build against. A separate sandbox key scope lets you test risk-free, strictly isolated from production paths.

Validate-only dry run

A sandbox create endpoint checks your payload and returns success without creating anything — no DB writes, no jobs, no email.

Stable demo data

Read endpoints serve fixed demo IDs you can copy-paste straight into your integration tests.

OpenAPI + docs

A Scramble-generated OpenAPI spec for the sandbox, plus onboarding docs and a webhook-verification reference.

Built with

Laravel 12 · PostgreSQL 16 (JSONB audit) · local private storage · Blade + Alpine (CSP, no eval) · PDF.js + signature_pad · self-hosted SMTP (DKIM/SPF/DMARC) · self-hosted TSA · Docker + Coolify · dedoc/scramble (OpenAPI) · encrypted webhook-secret rotation · openssl cms/ts stateless verifier · embedded audit certificate · zero paid crypto dependencies.

Own your signature flow.

Self-host the motor. Keep the data only as long as the webhook takes.