# signing

Signers, signature capture, witnesses, and attestations

Canonical URL: https://docs.paradoc.dev/sdk/artifacts/form/signing/

The signing flow in Paradoc separates the concepts of **who can sign** (Signers) from **who they sign for** (Parties). This enables scenarios where one person signs for multiple parties, or an authorized representative signs on behalf of an organization.

## Signing Flow Overview

```typescript
// 1. Fill form with party data
const draft = form.fill({
  fields: { /* ... */ },
  parties: {
    landlord: { id: 'landlord-0', name: 'ABC Property LLC' },
    tenant: { id: 'tenant-0', name: 'Jane Smith' }
  }
})

// 2. Register signers with their adopted signatures
const withSigners = draft
  .addSigner('jane', {
    person: { name: 'Jane Smith' },
    adopted: {
      signature: { image: 'data:image/png;base64,...', method: 'drawn' },
      initials: { method: 'typed' }
    }
  })
  .addSigner('bob', {
    person: { name: 'Bob Manager' },
    adopted: {
      signature: { image: 'data:image/png;base64,...', method: 'drawn' }
    }
  })

// 3. Link signers to parties (who signs for whom)
const ready = withSigners
  .addSignatory('tenant', 'tenant-0', { signerId: 'jane' })
  .addSignatory('landlord', 'landlord-0', { signerId: 'bob', capacity: 'Managing Member' })

// 4. Prepare for signing (freezes data)
const signable = ready.prepareForSigning()

// 5. Capture signatures at template locations
const signed = signable
  .captureSignature('tenant', 'tenant-0', 'jane', 'tenant-final-sig')
  .captureSignature('landlord', 'landlord-0', 'bob', 'landlord-final-sig')

// 6. Add witnesses and attestations
const witnessed = signed
  .addWitness({ id: 'witness-0', party: { name: 'Sam Witness' } })
  .addAttestation({
    witnessId: 'witness-0',
    signature: { image: 'data:...', method: 'drawn', timestamp: new Date().toISOString() },
    attestsTo: [
      { role: 'tenant', partyId: 'tenant-0', signerId: 'jane' }
    ]
  })

// 7. Finalize
const executed = witnessed.finalize()
```

## Signer

A `Signer` represents a person who can sign documents, along with their adopted signature and initials.

```typescript
interface Signer {
  person: Person              // Who is signing (always a Person)
  adopted?: {
    signature?: AdoptedSignature  // Adopted signature image
    initials?: AdoptedSignature   // Adopted initials image
  }
}
```

| Name | Type | Description |
| --- | --- | --- |
| `person` | `Person` | The signer identity. Always a Person, never an Organization. |
| `adopted?` | `{ signature?, initials? }` | Container for adopted signature and initials |
| `adopted.signature?` | `AdoptedSignature` | The adopted signature image |
| `adopted.initials?` | `AdoptedSignature` | The adopted initials image |

### AdoptedSignature

An `AdoptedSignature` is a reusable signature or initials image that a signer has approved.

```typescript
interface AdoptedSignature {
  image?: string   // Base64-encoded image or data URI
  method: 'drawn' | 'typed' | 'uploaded' | 'certificate'
}
```

| Name | Type | Description |
| --- | --- | --- |
| `image?` | `string` | Base64-encoded signature image or data URI |
| `method` | `'drawn' \| 'typed' \| 'uploaded' \| 'certificate'` | Method used to create this signature |

## PartySignatory

A `PartySignatory` links a signer to a party, specifying who signs for whom.

```typescript
interface PartySignatory {
  signerId: string    // Reference to a Signer
  capacity?: string   // Role or title (CEO, Managing Member, etc.)
}
```

| Name | Type | Description |
| --- | --- | --- |
| `signerId` | `string` | Reference to a signer ID in the signers registry |
| `capacity?` | `string` | Capacity in which they sign (CEO, Managing Member, Attorney-in-fact, etc.) |

### Example: One Signer, Multiple Parties

```typescript
// Jane signs for herself as tenant AND as authorized representative for guarantor
const draft = form.fill({
  parties: {
    tenant: { id: 'tenant-0', name: 'Jane Smith' },
    guarantor: { id: 'guarantor-0', name: 'Smith Family Trust' }
  }
})
  .addSigner('jane', { person: { name: 'Jane Smith' }, adopted: { /* ... */ } })
  .addSignatory('tenant', 'tenant-0', { signerId: 'jane' })
  .addSignatory('guarantor', 'guarantor-0', { signerId: 'jane', capacity: 'Trustee' })
```

## SignatureCapture

A `SignatureCapture` records when and where a signature was placed in the document.

```typescript
interface SignatureCapture {
  role: string           // Party role ID (e.g., "landlord", "tenant")
  partyId: string        // The party ID
  signerId: string       // The signer ID
  locationId: string     // Template location identifier
  type: 'signature' | 'initials'
  timestamp: string      // ISO 8601 date-time
  image?: string         // Override image (if different from adopted)
  method?: 'drawn' | 'typed' | 'uploaded' | 'certificate'
}
```

| Name | Type | Description |
| --- | --- | --- |
| `role` | `string` | The role ID of the party (e.g., "landlord", "tenant") |
| `partyId` | `string` | The party ID (user-supplied) |
| `signerId` | `string` | The signer ID (references signers registry) |
| `locationId` | `string` | Unique identifier for this location in the template |
| `type` | `'signature' \| 'initials'` | Whether this is a full signature or initials |
| `timestamp` | `string` | ISO 8601 date-time when the capture occurred |
| `image?` | `string` | Override image (if different from adopted signature) |
| `method?` | `'drawn' \| 'typed' \| 'uploaded' \| 'certificate'` | Override method |

### Capturing Signatures

```typescript
const signable = draft.prepareForSigning()

// Capture using adopted signature
const signed = signable.captureSignature('tenant', 'tenant-0', 'jane', 'page-1-sig')

// Capture with override image (one-time signature)
const signed = signable.captureSignature('tenant', 'tenant-0', 'jane', 'page-1-sig', {
  image: 'data:image/png;base64,...',
  method: 'drawn'
})

// Capture initials
const initialed = signed.captureInitials('tenant', 'tenant-0', 'jane', 'page-1-init')
```

Each capture method checks its slot and throws, naming the value, when the role is not declared, the party is not filled for that role, or the signer does not sign for that party. A person party with no signatories signs for itself: pass its party id as `signerId`, with no `addSigner`. An organization with no signatories has no signer. On a sealed form, `locationId` must also be a `signatureMap` field assigned to that signer with the same type (`signature`, `initials`, `capacity`, or `printed_name`).

A slot takes one capture. Capturing the same role, party, signer, location, and type again throws. Forms are immutable, so to correct a capture, capture again from the form instance before the first capture.

### Finalizing

`finalize()` moves a signable form to the executed phase. On a sealed form, every `signatureMap` field that is not `required: false` must have a capture first, or `finalize()` throws and lists the missing slots. `date_signed` fields are stamped when the document is signed, so they are not checked.

## WitnessParty

A `WitnessParty` represents a witness who can attest to signatures.

```typescript
interface WitnessParty {
  id: string          // Unique identifier
  party: Person       // Witness identity (always a Person)
  notary?: boolean    // Whether this witness is a notary public
}
```

| Name | Type | Description |
| --- | --- | --- |
| `id` | `string` | Unique identifier for this witness |
| `party` | `Person` | The witness identity (always a Person, never an Organization) |
| `notary?` | `boolean` | Whether this witness is a notary public |

### Adding Witnesses

```typescript
const signable = draft.prepareForSigning()

// Add a regular witness
const withWitness = signable.addWitness({
  id: 'witness-0',
  party: { name: 'Sam Witness' }
})

// Add a notary
const withNotary = withWitness.addWitness({
  id: 'notary-0',
  party: { name: 'Nancy Notary' },
  notary: true
})
```

## Attestation

An `Attestation` records a witness's attestation to one or more party signatures. It names its witness exactly once: by `witnessId` or inline as `witness`. `addAttestation` rejects an attestation that names no witness, or names it both ways.

```typescript
type Attestation = {
  signature: Signature            // The witness's signature
  attestsTo: AttestationTarget[]  // Signatures being witnessed
} & (
  | { witnessId: string }         // Reference to declared witness
  | { witness: WitnessParty }     // Inline witness definition
)

interface AttestationTarget {
  role: string         // Role of the party being witnessed
  partyId: string      // Party ID
  signerId: string     // Signer ID
  locationId?: string  // Specific capture location (optional)
}
```

### Attestation Properties

| Name | Type | Description |
| --- | --- | --- |
| `witnessId?` | `string` | Reference to a pre-declared witness by ID. Give this or `witness`, not both |
| `witness?` | `WitnessParty` | Inline witness definition. Give this or `witnessId`, not both |
| `signature` | `Signature` | The witness signature |
| `attestsTo` | `AttestationTarget[]` | The party signatures this attestation witnesses |

### AttestationTarget Properties

| Name | Type | Description |
| --- | --- | --- |
| `role` | `string` | The role ID of the party being witnessed |
| `partyId` | `string` | The party ID whose signature is being witnessed |
| `signerId` | `string` | The signer ID whose signature is being witnessed |
| `locationId?` | `string` | The specific capture location being witnessed |

### Adding Attestations

```typescript
// Using a pre-declared witness
const attested = signable.addAttestation({
  witnessId: 'witness-0',
  signature: {
    image: 'data:image/png;base64,...',
    method: 'drawn',
    timestamp: new Date().toISOString()
  },
  attestsTo: [
    { role: 'tenant', partyId: 'tenant-0', signerId: 'jane' },
    { role: 'landlord', partyId: 'landlord-0', signerId: 'bob' }
  ]
})

// Using inline witness definition
const attested = signable.addAttestation({
  witness: { id: 'witness-1', party: { name: 'New Witness' } },
  signature: { /* ... */ },
  attestsTo: [{ role: 'tenant', partyId: 'tenant-0', signerId: 'jane' }]
})
```

## Signature Status

Check signature progress using status methods on `SignableForm`:

```typescript
// Get status for a specific role
const status = signable.getSignatureStatus('tenant')
// { required: 1, collected: 1, complete: true,
//   parties: [{ partyId: 'tenant-0', hasSignatory: true, hasCapture: true, witnessed: true }] }

// Get overall status
const overall = signable.getOverallSignatureStatus()
// { roles: { tenant: { required: 1, collected: 1, complete: true }, landlord: {...} },
//   complete: false, totalRequired: 2, totalCollected: 1 }
```

## Related

* [party](/sdk/artifacts/form/party) - Party role definitions
* [form](/sdk/artifacts/form) - Form lifecycle and methods
* [Signature primitive](/schemas/primitives/signature) - Signature data type
