npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xenterprises/fastify-xsignwell

v1.3.0

Published

Fastify plugin for SignWell document signing API integration

Readme

@xenterprises/fastify-xsignwell

Fastify plugin for the SignWell e-signature API. It gives consuming applications a single fastify.xSignwell namespace for document creation and sending, template management, bulk sends, webhook registration/signature verification, and embedded signing — with fail-fast option validation and structured API errors.

Install

npm install @xenterprises/fastify-xsignwell fastify@5

Minimal example

import Fastify from "fastify";
import xSignwell from "@xenterprises/fastify-xsignwell";

const fastify = Fastify();

await fastify.register(xSignwell, {
  apiKey: process.env.SIGNWELL_API_KEY, // the consumer owns env access
});

const doc = await fastify.xSignwell.documents.create({
  name: "Employment Agreement",
  recipients: [{ email: "[email protected]", name: "John Doe" }],
  files: [{ name: "agreement.pdf", url: "https://example.com/agreement.pdf" }],
});

The plugin never reads process.env itself — pass configuration in via the options object (e.g. testMode: process.env.NODE_ENV !== "production" in your own app code).

Options

| Name | Type | Default | Required | Description | |------|------|---------|----------|-------------| | apiKey | string | — | Yes | SignWell API key (non-empty string) | | baseUrl | string | https://www.signwell.com/api/v1 | No | API base URL override | | testMode | boolean | false | No | Send test_mode: true on document/bulk-send creation (SignWell won't deliver signing emails) | | active | boolean | true | No | Set false to disable the plugin entirely (no decorator is added) |

Registration throws immediately on a missing/invalid apiKey or a wrong-typed option — see Error behavior.

Decorators

The plugin adds a single decorator namespace: fastify.xSignwell. It adds no routes and no request decorators.

| Decorator | Description | |-----------|-------------| | fastify.xSignwell.config | Resolved plugin configuration (apiKey, baseUrl, testMode) | | fastify.xSignwell.documents | Document management methods (below) | | fastify.xSignwell.templates | Template management methods (below) | | fastify.xSignwell.bulkSend | Bulk send methods (below) | | fastify.xSignwell.webhooks | Webhook management + signature verification (below) | | fastify.xSignwell.me() | Promise<Object> — get current SignWell account info |

documents

| Method | Description | |--------|-------------| | create(params) | Create a document for signing. params: name (required), recipients (required, each needs email), files, draft, subject, message, metadata, testMode | | createFromTemplate(templateId, params) | Create a document from a template. params.recipients required | | get(documentId) | Get document details by ID | | list(params?) | List documents ({ page, limit }) | | send(documentId, params?) | Send a draft document | | remind(documentId) | Send a reminder to unsigned recipients | | remove(documentId) / delete(documentId) | Delete a document | | getCompletedPdf(documentId) | Get download URL for the completed PDF | | getEmbeddedSigningUrl(documentId, recipientId) | Get the embedded signing URL for a recipient | | getAuditTrail(documentId) | Get the document audit trail |

templates

| Method | Description | |--------|-------------| | get(templateId) | Get template by ID | | create(params) | Create a template. params.name required; optional files, recipients, fields, subject, message | | update(templateId, params) | Update an existing template | | remove(templateId) / delete(templateId) | Delete a template | | list(params?) | List templates ({ page, limit }) | | getFields(templateId) | Get template field definitions ([] when none) | | getRecipients(templateId) | Get template recipient placeholders ([] when none) |

bulkSend

| Method | Description | |--------|-------------| | get(bulkSendId) | Get bulk send by ID | | list(params?) | List bulk sends ({ page, limit }) | | create(params) | Create a bulk send. params.templateId and params.recipients (non-empty) required | | getCsvTemplate(templateId) | Get the CSV template for bulk upload | | validateCsv(templateId, csvContent) | Validate CSV content before sending | | getDocuments(bulkSendId, params?) | Get documents produced by a bulk send |

webhooks

| Method | Description | |--------|-------------| | list() | List registered webhooks | | create(params) | Register a webhook. params.callbackUrl required; optional event | | remove(webhookId) / delete(webhookId) | Delete a webhook | | events | Event type constants (below) | | verifySignature(payload, signature, secret) | Verify a webhook HMAC-SHA256 signature (boolean) | | parseEvent(payload) | Parse a webhook payload into { event, documentId, document, recipient, timestamp, raw } |

Webhook event constants

fastify.xSignwell.webhooks.events.DOCUMENT_COMPLETED  // "document.completed"
fastify.xSignwell.webhooks.events.DOCUMENT_SENT       // "document.sent"
fastify.xSignwell.webhooks.events.DOCUMENT_VIEWED     // "document.viewed"
fastify.xSignwell.webhooks.events.DOCUMENT_SIGNED     // "document.signed"
fastify.xSignwell.webhooks.events.DOCUMENT_DECLINED   // "document.declined"
fastify.xSignwell.webhooks.events.DOCUMENT_EXPIRED    // "document.expired"
fastify.xSignwell.webhooks.events.DOCUMENT_VOIDED     // "document.voided"
fastify.xSignwell.webhooks.events.RECIPIENT_COMPLETED // "recipient.completed"
fastify.xSignwell.webhooks.events.RECIPIENT_VIEWED    // "recipient.viewed"
fastify.xSignwell.webhooks.events.RECIPIENT_SIGNED    // "recipient.signed"
fastify.xSignwell.webhooks.events.RECIPIENT_DECLINED  // "recipient.declined"

Routes

None. The plugin only decorates the Fastify instance; handling inbound SignWell webhooks is the consumer's responsibility (use webhooks.verifySignature + webhooks.parseEvent in your own route).

Error behavior

Registration fails fast with a descriptive Error:

| Error | When | |-------|------| | xsignwell: missing required option \apiKey` (string), e.g. `app.register(xSignwell, { apiKey: 'sw_...' })`| NoapiKeypassed | |xsignwell: option `apiKey` must be a non-empty string, e.g. ...|apiKeynot a non-empty string | |xsignwell: option `baseUrl` must be a string, e.g. ...|baseUrlwrong type | |xsignwell: option `testMode` must be a boolean, e.g. ...|testModewrong type | |xsignwell: option `active` must be a boolean, e.g. ...|active` wrong type |

Method calls throw [xSignwell] <service>.<method>: <param> is required style errors on missing/invalid arguments, before any network call.

API errors: a non-2xx SignWell response throws an Error with the API's message plus two extra properties for programmatic handling:

try {
  await fastify.xSignwell.documents.get("bad_id");
} catch (err) {
  err.statusCode;     // 404
  err.signwellError;  // { message: "Document not found", ... }
}

Network failures throw [xSignwell] Network error calling <endpoint>: <message>.

Requirements

  • Node.js >= 20
  • Fastify >= 5 (peer dependency)

Testing

npm test       # node --test, fully offline (SignWell API mocked via fetch stub)
npm run lint   # biome check src/ test/

License

Proprietary — All Rights Reserved, X Enterprises. See LICENSE.