@insigner/sdk
v1.0.1
Published
Official TypeScript SDK for the inSigner Cloud e-signature API
Maintainers
Readme
@insigner/sdk
Official TypeScript SDK for the inSigner Cloud e-signature API.
- ✅ Zero dependencies — uses native
fetch - ✅ Universal — Node.js 18+, Deno, Bun, Cloudflare Workers
- ✅ Full TypeScript — complete type definitions
- ✅ Auto-retry — exponential backoff on 429/5xx
- ✅ Pagination — cursor-based with async iterators
- ✅ File uploads — Buffer, Blob, ReadableStream, or file path
Installation
npm install @insigner/sdkQuick Start
import { InSigner } from '@insigner/sdk';
const client = new InSigner('isk_your_api_key');
// Create a document
const doc = await client.documents.create({ name: 'Sales Contract' });
// Upload a PDF
await client.documents.upload(doc.id, './contract.pdf');
// Add a signer
await client.documents.signers(doc.id).create({
name: 'Jane Doe',
email: '[email protected]',
role: 'signer',
});
// Add a signature field
await client.documents.fields(doc.id).create({
type: 'signature',
page: 1,
x: 100,
y: 500,
width: 200,
height: 50,
required: true,
});
// Send for signing
await client.documents.send(doc.id, { message: 'Please sign this contract.' });Configuration
const client = new InSigner('isk_...', {
baseUrl: 'https://app.insigner.co/api/v1', // default
maxRetries: 3, // default
timeout: 30000, // default, in ms
});Resources
Documents
// CRUD
const doc = await client.documents.create({ name: 'NDA' });
const docs = await client.documents.list({ limit: 10 });
const detail = await client.documents.get('doc_id');
await client.documents.update('doc_id', { name: 'Updated NDA' });
await client.documents.delete('doc_id');
// Upload & Download
await client.documents.upload('doc_id', './file.pdf');
const pdf = await client.documents.download('doc_id'); // ArrayBuffer
// Actions
await client.documents.send('doc_id');
await client.documents.cancel('doc_id');
// Audit trail
const events = await client.documents.audit('doc_id');
// Auto-pagination
for await (const doc of client.documents.listAll({ limit: 50 })) {
console.log(doc.name);
}Signers
const signers = client.documents.signers('doc_id');
await signers.create({ name: 'John', email: '[email protected]' });
const list = await signers.list();
await signers.update('signer_id', { name: 'John Doe' });
await signers.remind('signer_id');
await signers.delete('signer_id');Fields
const fields = client.documents.fields('doc_id');
await fields.create({
type: 'signature',
page: 1, x: 100, y: 500,
width: 200, height: 50,
});
const list = await fields.list();
await fields.update('field_id', { required: true });
await fields.delete('field_id');Attachments
const attachments = client.documents.attachments('doc_id');
await attachments.create(fileBuffer, 'extra.pdf');
const list = await attachments.list();
await attachments.delete('att_id');Templates
const templates = await client.templates.list();
const tpl = await client.templates.get('tpl_id');
const doc = await client.templates.use('tpl_id', {
name: 'From Template',
signers: [{ roleId: 'role_1', name: 'Jane', email: '[email protected]' }],
});Webhooks
// CRUD
const wh = await client.webhooks.create({
url: 'https://example.com/webhook',
events: ['document.completed', 'signer.signed'],
});
await client.webhooks.update(wh.id, { active: false });
await client.webhooks.test(wh.id);
const { secret } = await client.webhooks.rotateSecret(wh.id);
const deliveries = await client.webhooks.deliveries(wh.id);
await client.webhooks.delete(wh.id);
// Verify webhook signature
const isValid = await client.webhooks.verify(
rawBody, // string or Uint8Array
signatureHeader, // from X-InSigner-Signature header
webhookSecret,
);Campaigns
const campaign = await client.campaigns.create({ name: 'Q1 Onboarding' });
const list = await client.campaigns.list();
await client.campaigns.update(campaign.id, { name: 'Q2 Onboarding' });
const subs = await client.campaigns.submissions(campaign.id);
await client.campaigns.delete(campaign.id);Bulk Sends
const bulk = await client.bulkSends.create({
name: 'January batch',
templateId: 'tpl_id',
recipients: [
{ name: 'Alice', email: '[email protected]' },
{ name: 'Bob', email: '[email protected]' },
],
});
const status = await client.bulkSends.get(bulk.id);Organization
const org = await client.organization.get();
const members = await client.organization.members();
const logs = await client.organization.apiLogs({ limit: 50 });
const auditLogs = await client.organization.auditLogs({ limit: 20 });
// Verify a document by its hash
const result = await client.organization.verify({ hash: 'sha256:...' });Error Handling
import {
InSignerError,
AuthenticationError,
RateLimitError,
NotFoundError,
ValidationError,
} from '@insigner/sdk';
try {
await client.documents.get('nonexistent');
} catch (err) {
if (err instanceof NotFoundError) {
console.log('Document not found');
} else if (err instanceof AuthenticationError) {
console.log('Invalid API key');
} else if (err instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${err.retryAfter}s`);
} else if (err instanceof ValidationError) {
console.log('Validation errors:', err.errors);
} else if (err instanceof InSignerError) {
console.log(`API error ${err.status}: ${err.message}`);
}
}Idempotency
await client.documents.create(
{ name: 'Contract' },
{ idempotencyKey: 'unique-request-id-123' },
);⚠️ Security
Never use this SDK in client-side browser code. Your API key would be visible in the browser's network inspector and JavaScript source. Always call the inSigner API from your server (Node.js, Deno, Bun, or Cloudflare Workers).
// ❌ DON'T — React/Vue/Next.js frontend component
const client = new InSigner(process.env.NEXT_PUBLIC_API_KEY); // exposed!
// ✅ DO — Server-side API route or server action
const client = new InSigner(process.env.INSIGNER_API_KEY); // safeStore your API key in environment variables — never hardcode it in source files.
License
MIT © inSigner
