Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.spitshake.io/llms.txt

Use this file to discover all available pages before exploring further.

Witness Signatures

Witness signatures add a layer of verification to the signing process. After a signer completes their portion of a document, they can invite a witness to co-sign. The witness receives a signing invitation and must complete their own signature fields before the submission is finalized.

How it works

  1. A template defines a Witness submitter role with signature fields assigned to it.
  2. The primary signer completes their form (fills all their fields and submits).
  3. After completion, the signer is presented with an option to invite a witness.
  4. The signer enters the witness’s name and email address.
  5. DocuTrust sends the witness a signing invitation email.
  6. The witness opens the link, reviews the document, and completes their signature fields.
  7. Once the witness completes, the submission moves to the next step (or finishes if all roles are done).

API endpoint

Invite a witness

POST /s/:slug/invite_witness After completing their form, a signer can invite a witness by calling this endpoint with the signer’s signing slug.
curl -X POST "https://your-app.com/s/aB3kL9mNpQ/invite_witness" \
  -H "Content-Type: application/json" \
  -d '{
    "witness_name": "Sarah Johnson",
    "witness_email": "sarah.johnson@example.com",
    "message": "Hi Sarah, I have just signed an employment agreement and need you to witness it. Please review and add your signature."
  }'
Request parameters:
ParameterTypeRequiredDescription
witness_namestringYesFull name of the witness.
witness_emailstringYesEmail address where the witness invitation will be sent. Must differ from the signer’s email.
messagestringNoOptional custom message included in the witness invitation email.
Response (200 OK):
{
  "success": true,
  "witness": {
    "id": 305,
    "uuid": "e5f6a7b8-c9d0-1234-ef01-456789012345",
    "slug": "w2x6y3z7",
    "email": "sarah.johnson@example.com",
    "name": "Sarah Johnson",
    "role": "Witness",
    "status": "sent",
    "phone": null,
    "external_id": null,
    "metadata": {
      "invited_by_submitter_id": 301,
      "invited_by_email": "jane@example.com",
      "invited_by_name": "Jane Smith"
    },
    "values": {},
    "preferences": {
      "send_email": true,
      "sign_mode": "normal"
    },
    "embed_src": "https://your-app.com/s/w2x6y3z7",
    "opened_at": null,
    "sent_at": "2026-04-09T14:35:00.000Z",
    "completed_at": null,
    "declined_at": null,
    "submission_id": 187,
    "template_id": 42
  },
  "submission": {
    "id": 187,
    "slug": "n3k8p1w5",
    "status": "pending",
    "template_id": 42,
    "submitter_count": 3,
    "created_at": "2026-04-08T10:31:00.000Z",
    "updated_at": "2026-04-09T14:35:00.000Z",
    "completed_at": null,
    "expire_at": "2026-05-08T10:31:00.000Z",
    "archived_at": null
  }
}

Validation rules

The endpoint enforces the following rules. Violations return an HTTP 422 response with a descriptive error message.
RuleError message
The signer must have completed their form (status = completed)."Signer has not completed their form yet."
The witness email must differ from the signer’s email."Witness email cannot be the same as the signer's email."
The template must define a Witness submitter role."Template does not have a Witness role defined."
A witness has not already been invited for this signer."A witness has already been invited for this submission."
The submission must not be completed, expired, or archived."Submission is no longer active."
Error response example (422):
{
  "error": "validation_error",
  "message": "Signer has not completed their form yet.",
  "details": {
    "submitter_id": 301,
    "submitter_status": "opened",
    "required_status": "completed"
  }
}

Audit events

Witness actions are recorded in the immutable audit trail:
EventDescriptionRecorded data
witness_invitedA signer invited a witness.Signer ID, signer email, witness email, witness name, IP address, timestamp.
witness_form_sentThe witness invitation email was sent.Witness submitter ID, witness email, timestamp.
witness_form_viewedThe witness opened the signing link.Witness submitter ID, witness IP, user agent, timestamp.
witness_completedThe witness completed their signature.Witness submitter ID, witness email, witness IP, signed fields, timestamp.
witness_declinedThe witness declined to sign.Witness submitter ID, witness email, decline reason, timestamp.
Audit log entry example:
{
  "event": "witness_invited",
  "timestamp": "2026-04-09T14:35:00.000Z",
  "actor": "jane@example.com",
  "ip_address": "198.51.100.22",
  "details": {
    "signer_submitter_id": 301,
    "signer_email": "jane@example.com",
    "signer_name": "Jane Smith",
    "witness_submitter_id": 305,
    "witness_email": "sarah.johnson@example.com",
    "witness_name": "Sarah Johnson",
    "submission_id": 187,
    "template_id": 42
  }
}

Webhook events

When a witness is invited or completes signing, webhook events are dispatched to all configured endpoints:

form.created (witness)

Fired when the witness signing form is created and the invitation is sent.
{
  "event": "form.created",
  "timestamp": "2026-04-09T14:35:00Z",
  "data": {
    "submitter": {
      "id": 305,
      "uuid": "e5f6a7b8-c9d0-1234-ef01-456789012345",
      "email": "sarah.johnson@example.com",
      "name": "Sarah Johnson",
      "role": "Witness",
      "status": "sent",
      "external_id": null,
      "metadata": {
        "invited_by_submitter_id": 301,
        "invited_by_email": "jane@example.com",
        "invited_by_name": "Jane Smith"
      },
      "opened_at": null,
      "completed_at": null,
      "declined_at": null
    },
    "submission": {
      "id": 187,
      "slug": "n3k8p1w5",
      "status": "pending",
      "template_id": 42
    },
    "template": {
      "id": 42,
      "name": "Service Agreement"
    }
  }
}

form.completed (witness)

Fired when the witness completes their signature.
{
  "event": "form.completed",
  "timestamp": "2026-04-09T15:10:00Z",
  "data": {
    "submitter": {
      "id": 305,
      "uuid": "e5f6a7b8-c9d0-1234-ef01-456789012345",
      "email": "sarah.johnson@example.com",
      "name": "Sarah Johnson",
      "role": "Witness",
      "status": "completed",
      "external_id": null,
      "metadata": {
        "invited_by_submitter_id": 301,
        "invited_by_email": "jane@example.com",
        "invited_by_name": "Jane Smith"
      },
      "opened_at": "2026-04-09T15:00:00Z",
      "completed_at": "2026-04-09T15:10:00Z",
      "declined_at": null
    },
    "submission": {
      "id": 187,
      "slug": "n3k8p1w5",
      "status": "completed",
      "template_id": 42
    },
    "template": {
      "id": 42,
      "name": "Service Agreement"
    }
  }
}

Template setup

To enable witness signatures, your template must include a Witness submitter role. The Witness role should have at minimum a signature field assigned to it.
{
  "submitters": [
    {
      "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Client"
    },
    {
      "uuid": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "name": "Company Representative"
    },
    {
      "uuid": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "name": "Witness"
    }
  ],
  "schema": [
    {
      "uuid": "d4e5f6a7-b8c9-0123-def0-234567890123",
      "name": "Witness Signature",
      "type": "signature",
      "submitter_uuid": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "required": true,
      "readonly": false,
      "key": "witness_signature",
      "default_value": null,
      "placeholder": null,
      "options": null,
      "areas": [
        {
          "page": 2,
          "x": 0.55,
          "y": 0.82,
          "w": 0.30,
          "h": 0.06,
          "attachment_uuid": "e5f6a7b8-c9d0-1234-ef01-456789012345"
        }
      ]
    },
    {
      "uuid": "e5f6a7b8-c9d0-1234-ef01-567890123456",
      "name": "Witness Name",
      "type": "text",
      "submitter_uuid": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "required": true,
      "readonly": false,
      "key": "witness_name",
      "default_value": null,
      "placeholder": "Enter your full name",
      "options": null,
      "areas": [
        {
          "page": 2,
          "x": 0.55,
          "y": 0.78,
          "w": 0.30,
          "h": 0.03,
          "attachment_uuid": "e5f6a7b8-c9d0-1234-ef01-456789012345"
        }
      ]
    },
    {
      "uuid": "f6a7b8c9-d0e1-2345-f012-678901234567",
      "name": "Witness Date",
      "type": "date",
      "submitter_uuid": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "required": true,
      "readonly": false,
      "key": "witness_date",
      "default_value": "today",
      "placeholder": "MM/DD/YYYY",
      "options": null,
      "areas": [
        {
          "page": 2,
          "x": 0.55,
          "y": 0.90,
          "w": 0.20,
          "h": 0.03,
          "attachment_uuid": "e5f6a7b8-c9d0-1234-ef01-456789012345"
        }
      ]
    }
  ]
}
You can also use the embed component with data-role="Witness" to render only the witness portion of the form for integration into your own witness invitation flow.
The witness signing URL returned in embed_src can be used to embed the witness form directly in your application, bypassing the email invitation flow entirely.