SignStack

Agreement infrastructure for developers. Define your data, compose your contracts, run via API.

The Problem

Traditional e-signature platforms are document-centric. You upload a PDF, manually place fields at pixel coordinates, and write custom backend code to bridge the gap between your application data and the document. Your app already has structured business objects — employees, deals, clients, invoices — but the signing tool doesn't understand them.

Every time the document changes, your field mappings break. Every new contract type means another round of manual setup. Scaling means more glue code, more maintenance, more drift between your data and your documents.

A Different Approach: Data First

SignStack starts with your data, not your documents.

You define your business entities as JSON Schemas — the same data structures you already use in your application. Documents are a rendering concern. SignStack maps your structured data onto documents using JSONata expressions, so fields are always in sync with reality.

Your Data (employee, deal_info, company)
    ↓ typed by Schemas
Blueprint (orchestrates who signs what) ──→ Template (transforms and renders the document)
    ↓ runs as
Workflow (live, stateful signing instance — triggered via API)

The same employee schema can power an offer letter, an NDA, and a benefits enrollment form. Change the schema once, all documents adapt. No custom backend code.

Deep dive: The Data-First Principle →

Five Composable Primitives

SignStack gives you five building blocks. They compose together like LEGO to form any agreement workflow.

Primitive What It Does
Schema Defines the shape of a business entity (employee, deal_info). Your data contract.
Blueprint Orchestrates the full workflow — who signs what, when, with what data.
Template Connects data to a document. Maps entity fields onto the asset using expressions. The view layer.
Asset Wraps a file — HTML template, PDF, CSS, image. The raw content layer.
Function Reusable business logic (format_currency, calculate_tax). Shared across primitives.

A Workflow is a live instance of a Blueprint, created when you provide real entity data.

Here's what they actually look like:

apiVersion: signstack/v1beta2
kind: Blueprint
metadata:
  key: consulting_agreement
  version: 1.0.0
spec:
  inputs:
    - { key: consultant, schema: consultant@1.0.0 }
    - { key: company,    schema: company@1.0.0 }
  participants:
    - key: company_rep
      email: { expr: '$.company.representative.email' }
    - key: consultant_signer
      email: { expr: '$.consultant.email' }
  envelopes:
    - key: agreement
      documents:
        - { key: contract, template: consulting_agreement@1.0.0 }
  orchestration:
    key: root
    type: group
    execution: sequential
    children:
      - { key: company_signs,    type: participant, participant: company_rep }
      - { key: consultant_signs, type: participant, participant: consultant_signer }
apiVersion: signstack/v1beta2
kind: Template
metadata:
  key: consulting_agreement
  version: 1.0.0
spec:
  type: html
  content: consulting_agreement_html@1.0.0
  inputs:
    - { key: consultant, schema: consultant@1.0.0 }
    - { key: company,    schema: company@1.0.0 }
  data:
    transform: |
      {
        "consultant_name": $.consultant.firstName & ' ' & $.consultant.lastName,
        "company_name": $.company.name,
        "rate": '
& $formatNumber($.consultant.rate, '#,##0.00') & '/hr' } roles: - { key: consultant_signer } - { key: company_rep }
apiVersion: signstack/v1beta2
kind: Asset
metadata:
  key: consulting_agreement_html
  version: 1.0.0
spec:
  type: html
  styles:
    - agreement_styles@1.0.0
  data:
    schema: agreement_context@1.0.0
  content: |
    <h1>Consulting Services Agreement</h1>
    <p>Between <strong>{{company_name}}</strong> and
       <strong>{{consultant_name}}</strong>.</p>
    <p>Rate: {{rate}}</p>
    <div data-field="company_signature"    data-type="signature" data-role="company_rep"></div>
    <div data-field="consultant_signature" data-type="signature" data-role="consultant_signer"></div>
apiVersion: signstack/v1beta2
kind: JsonataFunction
metadata:
  key: format_currency
  version: 1.0.0
spec:
  params:
    - { name: amount, type: number }
  returnType:
    type: string
  body: "'
& $formatNumber(amount, '#,##0.00')"
apiVersion: signstack/v1beta2
kind: Schema
metadata:
  key: consultant
  version: 1.0.0
spec:
  jsonSchemaDraft: 2020-12
  schemaDefinition:
    type: object
    properties:
      firstName: { type: string }
      lastName:  { type: string }
      email:     { type: string, format: email }
      rate:      { type: number }
    required: [firstName, lastName, email]

Expressive. Compose these five primitives to model essentially any agreement workflow: single-signer NDAs, multi-party contracts with parallel signing, approval chains with conditional routing, quorum-based board resolutions, workflows that update entity data mid-flight, and documents that appear only when business rules are satisfied. Render from HTML (dynamic, data-driven) or existing PDFs (fixed-layout forms).

Dependable. Every entity is schema-validated before a document is rendered. Every published primitive is immutable — a workflow running against blueprint@1.0.0 today will behave identically a year from now. Every step, signature, and entity change is captured in an audit trail.

Reusable. The same employee schema powers your offer letter, NDA, and benefits enrollment. That NDA template in turn shows up in your hiring, vendor, and contractor blueprints. Your legal footer asset lives in every document. A format_currency function works identically in every expression. Design each primitive once, reuse it everywhere.

Easy to compose. AI is built into the Studio and CLI (and available as a SignStack Skill for your own AI coding tools) — describe the agreement and it composes the right primitives for you. Iterate with prompts; directly edit YAML only when you want to.

Three Interfaces, Same Primitives

Every interface produces the same underlying primitives. A blueprint built in Studio, written in the CLI, or created via the API is the same resource — stored the same way, runs the same way.

Interface What It Does
Studio Visual workspace for describing, previewing, publishing, and running workflows. AI built in.
CLI Version-controlled primitives in git. Generate, preview, push, and run from your terminal. AI built in.
REST API Create and manage primitives, trigger workflows, and respond to events — programmatically from your application.

White-Label & Embeddable

SignStack is built to disappear inside your product. You keep the brand; SignStack provides the infrastructure.

  • Your brand, end-to-end. Every email, signing page, and completed document carries your sender identity, logo, company info, and contact details. Embedded components inherit your app's styling automatically, so in-product surfaces match your design system without extra work.
  • Built for multi-tenancy. A namespace is an isolated environment inside your SignStack organization — primitives, workflows, branding, and API keys are scoped inside and never cross over. Give every tenant their own namespace and their own identity with zero risk of data leaking between them. Read more →
  • Embed anything from Studio. Resource editing, workflow editing, workflow monitoring, and e-signing — all available as framework-agnostic web components you drop into your own app. Most render inline; e-signing uses a sandboxed iframe for security.

Your Agreements, In Git

SignStack's own versioning — immutable published versions like blueprint@1.0.0 — gives you stable, auditable runtime behavior. On top of that, the primitives are plain YAML files that live in your repo alongside your application code, so you get your entire developer toolchain for free:

  • Git history for every change to every contract definition
  • Pull request reviews before deploying agreement changes
  • CI/CD pipelines that validate and push primitives automatically
  • Branching to test contract changes in isolation before merging
my-project/
├── blueprint.yaml       # Blueprint
├── templates.yaml       # Templates
├── assets.yaml          # Assets
├── functions.yaml       # Functions
├── schemas.yaml         # Schemas
├── definitions/         # JSON Schemas
├── html/                # HTML / Handlebars
└── css/

Who Uses SignStack

  • SaaS teams embedding white-label agreement infrastructure into their product
  • Developers who want infrastructure-as-code for agreements — YAML definitions, Git version control, CLI-driven deployments
  • Teams needing data-driven automation — conditional logic, parallel approvals, dynamic documents that react to business data
  • AI agents and workflow platforms that need a structured, auditable way to incorporate signatures and approvals into automated processes

Ready to Start?

Head to the Quick Start to build your first agreement workflow — in Studio, in your terminal, or straight from the API.