Sovos Docs

About Webhook Receiver Service

The Webhook Receiver Service allows your application to receive real-time notifications about envelope status changes from Sovos Signer.

When an envelope reaches a final state in Sovos Signer, the system sends a POST request to your configured webhook endpoint. This enables your application to respond immediately to envelope events without polling the API.

Download public specification

How it works

The webhook notification flow works as follows:

  1. You configure a webhook URL in your Sovos Signer account.

  2. An envelope in your account reaches a final status (completed, rejected, canceled, or expired).

  3. Sovos Signer sends a POST request to your webhook URL with details about the envelope event.

  4. Your application receives the notification and processes it.

  5. Your endpoint returns a 200 status code to confirm receipt.

Prerequisites

Before you implement webhook receivers, ensure you have:

  • A publicly accessible HTTPS endpoint that can receive POST requests.

  • The ability to process JSON payloads.

  • A valid Sovos Signer account with webhook configuration access. Contact the Professional Services team for more details on activating this service.

Available endpoints

The Webhook Receiver Service provides the following endpoints that correspond to different envelope final states. All webhook endpoints use the POST method and accept JSON payloads. Your implementation must respond with an HTTP 200 status code to confirm successful receipt.

All webhook notifications share the same request structure and payload format. The only difference is the endpoint path, which indicates the envelope event type.

EventMethodPathDescription
Envelope completedPOST/webhook-receiver/envelope/completedReceives notifications when an envelope is successfully completed with all required signatures.
Envelope rejectedPOST/webhook-receiver/envelope/rejectedReceives notifications when a signer rejects an envelope.
Envelope canceledPOST/webhook-receiver/envelope/cancelledReceives notifications when an envelope is canceled by the creator or an authorized user.
Envelope expiredPOST/webhook-receiver/envelope/expiredReceives notifications when an envelope expires before completion.
Envelope unprocessablePOST/webhook-receiver/envelope/unprocessableReceives notifications when an envelope cannot be processed due to system errors or invalid configuration.

Common request structure

Request headers
All webhook requests include the Content-Type: application/json header.
Response requirements
Your webhook endpoint must:
  • Return an HTTP 200 status code to acknowledge successful receipt.

  • Respond within 30 seconds to avoid timeout.

  • Return an empty response body or a simple JSON object.

Important:

If your endpoint returns a non-200 status code or times out, Sovos Signer will retry the notification using an exponential backoff strategy.

Error responses
If an error occurs during webhook delivery, Sovos Signer returns an error response with an HTTP error status code and a JSON body containing error details.

Webhook notification schema

All webhook notifications use the NotificationFinishedRequest payload structure, which includes envelope information, status details, and file attachments.

This example shows a completed envelope with one document file:

{
  "initiative": "5b1aea4b-8e58-4050-91cc-d320ff5c41cf",
  "envelopeId": "b16ea039-f2fe-4f8d-829a-d97698d367f1",
  "status": "COMPLETED",
  "reason": "All signers completed successfully",
  "documentFiles": [
    {
      "name": "contrato_12345.pdf",
      "mediaType": "application/pdf",
      "content": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDQ5Nj4+c3RyZWFtCniclZTPb..."
    }
  ],
  "generatedFiles": [
    {
      "name": "audit_trail_12345.pdf",
      "mediaType": "application/pdf",
      "content": "JVBERi0xLjYKJeLjz9MKNSAwIG9iago8PC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDYxOD4+c3RyZWFtCniclZbRc..."
    }
  ]
}

Where:

FieldTypeRequiredDescription
initiativestringYesUnique identifier for the initiative associated with the envelope.
envelopeIdstringYesUnique identifier for the envelope.
statusenumYesFinal status of the envelope. Possible values: COMPLETED, REJECTED, CANCELLED, EXPIRED, UNPROCESSABLE.
reasonstringYesExplanation for the status change.
documentFilesarrayYesList of processed document files included in the envelope. Each file contains name, mediaType, and content (Base64-encoded) of the file.
generatedFilesarrayYesList of files generated by the system, such as audit trails. Each file contains name, mediaType, and content (Base64-encoded) of the file.
Rejected envelope
When a signer rejects an envelope, the notification includes a specific reason. When an envelope is rejected, the generatedFiles array is typically empty because no signed documents are produced.

{
  "initiative": "5b1aea4b-8e58-4050-91cc-d320ff5c41cf",
  "envelopeId": "c27fb14a-a3gf-5g9e-93ab-e08709e478g2",
  "status": "REJECTED",
  "reason": "Signer declined: Terms not acceptable",
  "documentFiles": [],
  "generatedFiles": []
}
Cancelled envelope
The notification includes information about why the cancellation occurred.

{
  "initiative": "5b1aea4b-8e58-4050-91cc-d320ff5c41cf",
  "envelopeId": "d38gc25b-b4hg-6h0f-04bc-f19810f589h3",
  "status": "CANCELLED",
  "reason": "Cancelled by envelope creator: Contract terms changed",
  "documentFiles": [],
  "generatedFiles": []
}
Unprocessable envelope
This notification indicates system-level issues that prevented completion.

{
  "initiative": "5b1aea4b-8e58-4050-91cc-d320ff5c41cf",
  "envelopeId": "e49hd36c-c5ih-7i1g-15cd-g20921g690i4",
  "status": "UNPROCESSABLE",
  "reason": "System error: Unable to validate digital certificate",
  "documentFiles": [],
  "generatedFiles": []
}

Implementation example

This is a basic example of a webhook receiver in Node.js using Express:

const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook-receiver/envelope/completed', async (req, res) => {
  try {
    const payload = req.body;
    
    // Log the envelope completion
    console.log(`Envelope completed: ${payload.envelopeId}`);
    console.log(`Initiative: ${payload.initiative}`);
    console.log(`Status: ${payload.status}`);
    
    // Process document files
    for (const file of payload.documentFiles) {
      console.log(`Document: ${file.name} (${file.mediaType})`);
      // Decode base64 content and save file
      const buffer = Buffer.from(file.content, 'base64');
      // Save buffer to storage...
    }
    
    // Process generated files (signed documents, audit trails)
    for (const file of payload.generatedFiles) {
      console.log(`Generated file: ${file.name} (${file.mediaType})`);
      // Process generated files...
    }
    
    // Return 200 to acknowledge receipt
    res.status(200);
    
  } catch (error) {
    console.error('Error processing webhook:', error);
    res.status(500);
  }
});

app.listen(3000, () => {
  console.log('Webhook receiver listening on port 3000');
});