Blueprints
A Blueprint is the declarative definition of an agreement workflow — what data goes in, who signs, which documents they sign, and in what order. Design it once, run it many times with different data as live Workflows.
A Blueprint specifies:
- Inputs — what data is required (referencing Schemas)
- Participants — who will sign (with names/emails from expressions)
- Envelopes — groups of documents sent together (referencing Templates)
- Orchestration — the order and conditions for signing (sequential, parallel, quorum)
You design a Blueprint once — in Studio, in your repo as YAML, or via the API — and run it many times, each time with different data.
YAML Format
apiVersion: signstack/v1beta2
kind: Blueprint
metadata:
key: employee_onboarding # Required, snake_case
version: 1.0.0 # Required, semver
name: Employee Onboarding # Required
description: New hire offer + NDA + benefits
labels:
department: hr
spec:
inputs: # Data required at runtime
- key: employee
schema: employee@1.0.0
participants: # People who sign
- key: new_hire
name:
expr: '$full_name($.employee)'
email:
expr: '$.employee.email'
envelopes: # Document groups
- key: offer_envelope
documents:
- key: offer_letter
template: offer_letter@1.0.0
orchestration: # Signing order
key: root
type: group
execution: sequential
children:
- key: new_hire_signs
type: participant
participant: new_hire
action:
type: sign
envelope: offer_envelope
assignments:
- document: offer_letter
role: employee
functions: # Local alias → versioned function reference
full_name: get_full_name@1.0.0
Spec Fields
| Field | Required | Description |
|---|---|---|
inputs |
No | Data inputs required when running a workflow. Each references a Schema (key@version). |
participants |
No | People who perform actions. name and email can be literals or { expr: '...' }. |
envelopes |
Yes | Groups of documents. Each envelope has documents referencing Templates. |
orchestration |
No | Root step of the orchestration tree. If omitted, the workflow runs as a document generator — no signing or step routing. |
functions |
No | Custom function aliases. Keys used as #x3C;alias>() in expressions. |
Inputs
inputs:
- key: employee # Referenced as $.employee in expressions
name: Employee Information # Optional display name
schema: employee@1.0.0 # Schema for validation
required: true # boolean or JSONata expression
Participants
participants:
- key: new_hire
name:
expr: "$.employee.firstName & ' ' & $.employee.lastName"
email:
expr: '$.employee.email'
phone: # Optional
expr: '$.employee.phone'
Name, email, and phone can be literal strings or JSONata expressions pulling from inputs.
Envelopes & Documents
envelopes:
- key: offer_envelope
name: Offer Letter Package
subject: 'Your Offer Letter' # Email subject line
documents:
- key: offer_letter
name: Offer Letter
template: offer_letter@1.0.0
inputMap: # Optional: map template inputs to blueprint data
contact: '$.employee' # Template expects 'contact', blueprint has 'employee'
- key: enterprise_addendum
name: Enterprise Addendum
template: enterprise_addendum@1.0.0
includeIf: "$.client.tier = 'Enterprise'" # Optional: include only when expression is true
Input mapping: When blueprint and template input keys differ, use inputMap to bridge them. Matching keys are auto-mapped.
Orchestration Steps
Two step types:
Group — contains child steps:
- key: signing_phase
type: group
name: Signing Phase
execution: sequential # or parallel
completion: all # all, any, or quorum (set `quorum: N` when using quorum)
includeIf: '$.position.includesBenefits' # optional: skip phase entirely when false
children:
- ...child steps...
Participant — a signing task:
- key: new_hire_signs
type: participant
participant: new_hire
includeIf: '$.position.level > 3' # optional: skip step entirely when false
action:
type: sign
envelope: offer_envelope
assignments:
- document: offer_letter
role: employee
Steps can also run validation and update entity data on completion. See The Workflow Engine.
Execution Modes
| Mode | Behavior |
|---|---|
sequential |
Children execute one at a time, in order |
parallel |
All children execute concurrently |
Completion Rules (parallel groups)
| Rule | Behavior |
|---|---|
all |
Wait for every child (default) |
any |
Complete as soon as any one child finishes |
quorum |
Complete when N children finish (set quorum: N) |
Examples
Simple NDA (Single Participant)
apiVersion: signstack/v1beta2
kind: Blueprint
metadata:
key: simple_nda_workflow
version: 1.0.0
name: Simple NDA Workflow
spec:
inputs:
- key: signer_info
schema: contact@1.0.0
participants:
- key: signer
name:
expr: '$.signer_info.name'
email:
expr: '$.signer_info.email'
envelopes:
- key: nda_envelope
documents:
- key: nda
template: simple_nda@1.0.0
inputMap:
contact: '$.signer_info'
orchestration:
key: signer_signs_nda
type: participant
participant: signer
action:
type: sign
envelope: nda_envelope
assignments:
- document: nda
role: signer
Multi-Party Contract (Parallel Signing)
apiVersion: signstack/v1beta2
kind: Blueprint
metadata:
key: multi_party_contract
version: 1.0.0
name: Multi-Party Contract
spec:
inputs:
- key: party_a
schema: company@1.0.0
- key: party_b
schema: company@1.0.0
- key: contract_details
schema: contract_data@1.0.0
participants:
- key: party_a_signer
name:
expr: '$.party_a.representative.name'
email:
expr: '$.party_a.representative.email'
- key: party_b_signer
name:
expr: '$.party_b.representative.name'
email:
expr: '$.party_b.representative.email'
- key: witness
name:
expr: '$.contract_details.witness.name'
email:
expr: '$.contract_details.witness.email'
envelopes:
- key: contract_envelope
documents:
- key: main_contract
template: business_contract@1.0.0
inputMap:
details: '$.contract_details'
orchestration:
key: root
type: group
execution: sequential
children:
# Both parties sign in parallel
- key: signing_phase
type: group
execution: parallel
children:
- key: party_a_signs
type: participant
participant: party_a_signer
action:
type: sign
envelope: contract_envelope
assignments:
- document: main_contract
role: party_a
- key: party_b_signs
type: participant
participant: party_b_signer
action:
type: sign
envelope: contract_envelope
assignments:
- document: main_contract
role: party_b
# Witness signs after both parties
- key: witness_signs
type: participant
participant: witness
action:
type: sign
envelope: contract_envelope
assignments:
- document: main_contract
role: witness
Board Resolution (Quorum)
apiVersion: signstack/v1beta2
kind: Blueprint
metadata:
key: board_resolution
version: 1.0.0
name: Board Resolution Approval
spec:
inputs:
- key: resolution
schema: resolution@1.0.0
- key: board_members
schema: board_members@1.0.0
participants:
- key: board_member_1
name:
expr: '$.board_members[0].name'
email:
expr: '$.board_members[0].email'
- key: board_member_2
name:
expr: '$.board_members[1].name'
email:
expr: '$.board_members[1].email'
- key: board_member_3
name:
expr: '$.board_members[2].name'
email:
expr: '$.board_members[2].email'
envelopes:
- key: resolution_envelope
documents:
- key: resolution_doc
template: board_resolution@1.0.0
orchestration:
key: root
type: group
execution: sequential
children:
- key: board_approval
type: group
execution: parallel
completion: quorum
quorum: 2
children:
- key: member_1_signs
type: participant
participant: board_member_1
action:
type: sign
envelope: resolution_envelope
assignments:
- document: resolution_doc
role: board_member
- key: member_2_signs
type: participant
participant: board_member_2
action:
type: sign
envelope: resolution_envelope
assignments:
- document: resolution_doc
role: board_member
- key: member_3_signs
type: participant
participant: board_member_3
action:
type: sign
envelope: resolution_envelope
assignments:
- document: resolution_doc
role: board_member
Versioning
Blueprints use semantic versioning. A blueprint moves from Draft to a concrete published version (1.0.0); to make further changes, you cut a new version (1.1.0, 2.0.0). Published versions are immutable — every workflow running against 1.0.0 keeps behaving exactly as designed, even after 2.0.0 ships.
Draft → 1.0.0 (published, immutable)
↓ edit + publish
1.1.0 (published, immutable)
↓ edit + publish
2.0.0 (published, immutable)
Pick the version bump based on the change:
- MAJOR (2.0.0) — Breaking changes (removed inputs, changed orchestration)
- MINOR (1.1.0) — Backwards-compatible additions (new optional input, new step)
- PATCH (1.0.1) — Bug fixes (expression correction, name change)
Related Concepts
- Workflows — Live, stateful instances created when you run a Blueprint
- Templates — Documents that blueprints compose into envelopes
- Schemas — Data contracts for blueprint inputs
- Custom Functions — Reusable logic in blueprint expressions
- Workflow Engine — Deep dive into step execution
- Data-First Principle — Entity-driven architecture
