Skip to Content
GuidesBulk Signing

Bulk Signing

Bulk signing allows integration partners to sign hundreds of documents at once. This is ideal when one signer (e.g., a CEO) needs to sign many documents of the same type.

Overview

The bulk signing flow has three steps:

  1. Save a signature — Capture and store the signer’s signature image
  2. Create documents — Create documents from a template with signers and fields
  3. Bulk sign — Sign all documents at once using the saved signature

Step 1: Save a Signature

Before bulk signing, you need a saved signature for the signer. You can capture signatures using the <KoralaSignaturePad> React component or any other method that produces a base64 PNG data URL.

Format requirement: Signature images must be base64 PNG data URLs (data:image/png;base64,...). JPEG, SVG, and regular HTTP URLs are not supported. The maximum size is 500KB.

Using the React Signature Pad

import { KoralaSignaturePad } from '@korala/react'; function SignatureCapture() { return ( <KoralaSignaturePad onSignatureCreated={({ imageDataUrl }) => { // Send to your backend to save via Korala API fetch('/api/save-signature', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ signatureImageUrl: imageDataUrl, email: '[email protected]', name: 'Jane Smith', }), }); }} /> ); }

Saving via the API

import { KoralaClient } from '@korala/api-client'; const korala = new KoralaClient({ apiKeyId: process.env.KORALA_API_KEY_ID!, apiSecret: process.env.KORALA_API_SECRET!, }); const signature = await korala.signatures.create({ email: '[email protected]', name: 'Jane Smith', signatureImageUrl: 'data:image/png;base64,...', isDefault: true, }); console.log(`Saved signature: ${signature.id}`);

Managing Saved Signatures

// List signatures for a specific email const signatures = await korala.signatures.list({ email: '[email protected]' }); // Get a specific signature const signature = await korala.signatures.get(signatureId); // Delete a signature await korala.signatures.delete(signatureId);

Step 2: Create Documents

Create your documents using templates. See the Documents guide for details on creating and sending documents.

// Create 200 NDAs from a template const documentIds: string[] = []; for (const recipient of recipients) { const doc = await korala.templates.createDocument(templateId, { signerRoles: { 'Company Representative': { email: '[email protected]', name: 'Jane Smith', }, 'Recipient': { email: recipient.email, name: recipient.name, }, }, }); documentIds.push(doc.id); // Send for signing await korala.documents.send(doc.id); }

Step 3: Bulk Sign

Sign all documents at once using the saved signature:

const result = await korala.documents.bulkSign({ documentIds, signerEmail: '[email protected]', autoFillDateValue: '2026-02-18', // optional, defaults to today }); console.log(`Signed: ${result.signed}`); console.log(`Failed: ${result.failed}`); // Check individual results for (const doc of result.results) { if (doc.success) { console.log(`${doc.documentId}: signed (allSigned: ${doc.allSigned})`); } else { console.log(`${doc.documentId}: failed - ${doc.error}`); } }

How Auto-Fill Works

When bulk signing, the system automatically fills fields based on type:

Field TypeAuto-Fill Behavior
SignatureUses the signer’s default saved signature
InitialsUses the signer’s default saved signature
DateUses autoFillDateValue (defaults to today)
TextMust be pre-filled (e.g., via template variables)
CheckboxMust be pre-filled (e.g., via template variables)

Important: If no saved signature exists for the signer, any required Signature or Initials fields will fail with an error. You must save a signature via POST /signatures (Step 1) before calling bulk sign.

Per-Document Overrides

You can override specific field values for individual documents:

const result = await korala.documents.bulkSign({ documentIds: ['doc-1', 'doc-2', 'doc-3'], signerEmail: '[email protected]', documents: [ { documentId: 'doc-3', fields: [ // Override a text field value { fieldId: 'field-xyz', value: 'Special terms apply' }, // Override a signature field with a different signature image { fieldId: 'field-sig', value: 'Signed', signatureImageUrl: 'data:image/png;base64,...', }, ], }, ], });

Per-document overrides take precedence over auto-fill.

Note: All signature images must be base64 PNG data URLs (data:image/png;base64,...). Other formats (JPEG, SVG, regular URLs) are not supported and will be rejected by the API.

Handling Partial Success

Bulk sign always returns HTTP 200 with per-document results. Some documents may fail while others succeed:

const result = await korala.documents.bulkSign({ documentIds, signerEmail: '[email protected]', }); if (result.failed > 0) { const failures = result.results.filter((r) => !r.success); console.error('Failed documents:', failures); // Retry failed documents const retryIds = failures .filter((f) => f.error !== 'Signer has already signed') .map((f) => f.documentId); if (retryIds.length > 0) { await korala.documents.bulkSign({ documentIds: retryIds, signerEmail: '[email protected]', }); } }

Identifying Signers

You can identify the target signer by email or external ID:

// By email await korala.documents.bulkSign({ documentIds, signerEmail: '[email protected]', }); // By external ID await korala.documents.bulkSign({ documentIds, signerExternalId: 'user_123', });

Exactly one of signerEmail or signerExternalId must be provided.

IP Attribution

When your server calls the bulk sign API on behalf of end users, the audit trail records your server’s IP address. To preserve the real end-user IP for compliance, pass it via the X-Client-IP header. This value is stored separately as claimedIpAddress in the audit trail alongside the verified network IP.

const result = await korala.documents.bulkSign( { documentIds, signerEmail: '[email protected]', }, { clientIp: endUserIpAddress }, );

Note: The X-Client-IP value must be a valid IP address (IPv4 or IPv6). Invalid values are silently ignored. The header is validated but not verified — it represents the partner’s assertion of the end-user’s IP.

Limits

  • Maximum 500 documents per bulk sign request
  • Documents must be in Pending status
  • The target signer must not have already signed or declined

Response Format

{ "signed": 198, "failed": 2, "results": [ { "documentId": "doc-1", "success": true, "allSigned": true }, { "documentId": "doc-2", "success": true, "allSigned": false }, { "documentId": "doc-x", "success": false, "error": "Document not found" } ] }

When allSigned is true, the document has been queued for completion (cryptographic signing and timestamping). Listen for the document_completed webhook to know when the signed PDF is ready.

Last updated on