Loading...
Loading...
The SignBolt JavaScript SDK gives you a type-safe, promise-based client for the SignBolt REST API. Works in Node.js, Next.js, Bun, Cloudflare Workers, and modern browsers.
Fully typed (TypeScript definitions bundled)
Works in Node.js 18+, Edge runtimes, and modern browsers
Promise-based API with native async/await support
Automatic retries with exponential backoff on network errors
Webhook signature verification helper built in
The JavaScript SDK is distributed as an ESM and CommonJS package via npm. Node.js 18+ is required for native fetch support. For Node.js 16, install with the `node-fetch` peer dependency.
npm install @signbolt/sdkyarn add @signbolt/sdk # or pnpm add @signbolt/sdkGenerate an API key from your SignBolt dashboard at /dashboard under API Keys. API keys start with `sb_live_` (production) or `sb_test_` (sandbox). Never commit API keys to source control β store them as environment variables.
import { SignBolt } from '@signbolt/sdk';
// Load from environment variable
const client = new SignBolt({
apiKey: process.env.SIGNBOLT_API_KEY,
});
// With additional options
const client = new SignBolt({
apiKey: process.env.SIGNBOLT_API_KEY,
baseUrl: 'https://signbolt.au/api/v1', // default
timeout: 30000, // 30 seconds
maxRetries: 3,
});Send a document to a recipient for signature. The recipient receives an email with a signing link. Once they sign, you receive a webhook callback (if configured).
import { SignBolt } from '@signbolt/sdk';
import { readFile } from 'fs/promises';
const client = new SignBolt({
apiKey: process.env.SIGNBOLT_API_KEY,
});
async function sendContract() {
// Load the PDF from disk
const pdfBuffer = await readFile('./contracts/service-agreement.pdf');
// Send for signature
const response = await client.documents.send({
file: pdfBuffer,
filename: 'service-agreement.pdf',
recipients: [
{
email: 'client@example.com',
name: 'Jane Client',
role: 'signer',
},
],
subject: 'Please sign: Service Agreement',
message: 'Hi Jane, please review and sign the attached service agreement. Let me know if you have any questions.',
fields: [
{
type: 'signature',
page: 1,
x: 100,
y: 500,
width: 200,
height: 60,
required: true,
recipientEmail: 'client@example.com',
},
{
type: 'date',
page: 1,
x: 350,
y: 510,
width: 120,
height: 40,
required: true,
recipientEmail: 'client@example.com',
},
],
webhookUrl: 'https://api.yoursite.com/webhooks/signbolt',
expiresInDays: 14,
});
console.log('Document ID:', response.documentId);
console.log('Signing URL:', response.signingUrls[0].url);
console.log('Status:', response.status);
return response;
}
sendContract().catch(console.error);Verify incoming webhook signatures to ensure requests genuinely come from SignBolt. The SDK provides a verification helper that takes the raw request body, signature header, and your webhook secret.
import { SignBolt } from '@signbolt/sdk';
import express from 'express';
const app = express();
const webhookSecret = process.env.SIGNBOLT_WEBHOOK_SECRET;
const client = new SignBolt({ apiKey: process.env.SIGNBOLT_API_KEY });
// Capture raw body for signature verification
app.post('/webhooks/signbolt',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-signbolt-signature'];
// Verify the signature
const isValid = client.webhooks.verify({
body: req.body,
signature,
secret: webhookSecret,
});
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body.toString());
switch (event.type) {
case 'document.signed':
console.log(`Document ${event.data.documentId} was signed by ${event.data.signerEmail}`);
// Update your database, send notification, etc.
break;
case 'document.completed':
console.log(`Document ${event.data.documentId} is fully signed by all parties`);
// Download the final PDF, store in your system
break;
case 'document.declined':
console.log(`Signer declined: ${event.data.signerEmail}`);
// Notify the sender, update CRM
break;
case 'document.expired':
console.log(`Document ${event.data.documentId} expired without being signed`);
break;
default:
console.log('Unhandled event type:', event.type);
}
res.status(200).json({ received: true });
}
);
app.listen(3000, () => console.log('Webhook listener on :3000'));All SDK methods reject with a typed `SignBoltError` containing the HTTP status, error code, and message. Wrap calls in try/catch to handle errors cleanly.
import { SignBolt, SignBoltError } from '@signbolt/sdk';
const client = new SignBolt({ apiKey: process.env.SIGNBOLT_API_KEY });
async function sendWithErrorHandling(pdfBuffer) {
try {
const response = await client.documents.send({
file: pdfBuffer,
filename: 'contract.pdf',
recipients: [{ email: 'client@example.com', name: 'Client' }],
fields: [{ type: 'signature', page: 1, x: 100, y: 500, width: 200, height: 60 }],
});
return response;
} catch (error) {
if (error instanceof SignBoltError) {
switch (error.statusCode) {
case 400:
console.error('Bad request:', error.message);
// Inspect error.details for field-level validation errors
break;
case 401:
console.error('Invalid API key β check your credentials');
break;
case 403:
console.error('API access requires Business plan β upgrade at /pricing');
break;
case 413:
console.error('PDF exceeds 25MB β compress or split before sending');
break;
case 429:
console.error('Rate limited β backing off and retrying');
// SDK retries automatically up to maxRetries; beyond that, back off in app code
break;
case 500:
case 502:
case 503:
console.error('SignBolt server error β transient, safe to retry');
break;
default:
console.error('SignBolt error:', error.message);
}
throw error;
} else {
// Non-SignBolt error (network, parsing, etc.)
console.error('Unexpected error:', error);
throw error;
}
}
}List signed documents with pagination and filtering.
import { SignBolt } from '@signbolt/sdk';
const client = new SignBolt({ apiKey: process.env.SIGNBOLT_API_KEY });
// Get recent signed documents
async function getRecentSigned() {
const page1 = await client.documents.list({
status: 'completed',
limit: 50,
cursor: null,
});
console.log(`Got ${page1.data.length} documents`);
// Paginate
if (page1.nextCursor) {
const page2 = await client.documents.list({
status: 'completed',
limit: 50,
cursor: page1.nextCursor,
});
console.log(`Got another ${page2.data.length} documents`);
}
}
// Filter by date range
async function getDocsForMarch() {
const docs = await client.documents.list({
createdAfter: '2026-03-01T00:00:00Z',
createdBefore: '2026-04-01T00:00:00Z',
limit: 100,
});
for (const doc of docs.data) {
console.log(`${doc.filename} β signed by ${doc.signerEmail} on ${doc.signedAt}`);
}
}The SignBolt API enforces rate limits to ensure fair use across all customers. The SDK respects these limits with automatic retries.
Standard rate limit: 60 requests per minute per API key.
Burst allowance: up to 120 requests in a 60-second window, subject to overall hourly limits.
Hourly limit: 3,000 requests per API key per hour.
Send endpoint specifically limited to 10 documents per minute to protect email deliverability.
Enterprise customers can request higher limits via enterprise@signbolt.au.
Yes, the SDK works in modern browsers that support native fetch (Chrome, Edge, Firefox, Safari). However, you should never expose your SignBolt API key in client-side code β that would allow anyone to use your SignBolt account. Use the SDK on your backend (Node.js, Next.js API routes, Cloudflare Workers) and expose your own API that proxies to SignBolt.
Yes. Use the SDK in Next.js API routes, Server Actions, or Route Handlers. The SDK is compatible with both Node.js and Edge runtimes. For Next.js App Router, place the SDK calls in `'use server'` functions or route handlers under `app/api/`.
PDF uploads of any size up to 25MB complete in a single request. Webhook callbacks deliver completion events asynchronously. The SDK uses promises throughout and does not block the event loop.
The SDK automatically retries rate-limited requests with exponential backoff up to `maxRetries` (default 3). If you consistently hit rate limits, implement application-level backoff or contact support about increasing your limit. For bulk operations, the `sendBulk` method handles rate-limit-friendly batching automatically.
Yes. The SDK uses native fetch and works in any runtime with fetch support. Edge runtimes have no Node.js API dependencies. Keep the API key in platform-native environment variables (Worker secrets, Vercel env vars).
Use a sandbox API key (prefix `sb_test_`). Requests with sandbox keys behave identically to production but do not actually send emails or bill against your plan limits. Swap keys in production via environment variables.
The SignBolt JavaScript SDK source is available on GitHub under the MIT license. Contributions and issues welcome. The SDK is thin β most of the value is in consistent typing and webhook verification; you can absolutely use the raw REST API if you prefer.
API access is included in the Business plan ($24/month). Upgrade to get your API key.