Bulk Sending
Bulk Send lets you send the same template to up to 500 recipients in a single API call. Each recipient gets their own individual document with a unique signing link.
Prerequisites
Section titled “Prerequisites”Before creating a bulk send, you need:
- A template with at least one signer slot and fields configured
- An API key with
bulk_sends.createscope - A list of signers with names and emails
Creating a bulk send
Section titled “Creating a bulk send”curl -X POST https://app.insigner.co/api/v1/bulk-sends \ -H "Authorization: Bearer isk_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "templateId": "tpl_abc123", "name": "Q3 Vendor Agreements", "emailMessage": "Hi! Please review and sign your vendor agreement for Q3 2026.", "signers": [ { "name": "Alice Johnson", "email": "alice@vendor-a.com" }, { "name": "Bob Williams", "email": "bob@vendor-b.com" }, { "name": "Carol Davis", "email": "carol@vendor-c.com", "phone": "+1555123456" } ] }'const signers = [ { name: 'Alice Johnson', email: 'alice@vendor-a.com' }, { name: 'Bob Williams', email: 'bob@vendor-b.com' }, { name: 'Carol Davis', email: 'carol@vendor-c.com', phone: '+1555123456' },];
const { data } = await insignerFetch('/bulk-sends', { method: 'POST', body: JSON.stringify({ templateId: 'tpl_abc123', name: 'Q3 Vendor Agreements', emailMessage: 'Please review and sign your vendor agreement for Q3 2026.', signers })});
console.log(`Bulk send complete: ${data.sentCount}/${data.totalCount} sent`);signers = [ {"name": "Alice Johnson", "email": "alice@vendor-a.com"}, {"name": "Bob Williams", "email": "bob@vendor-b.com"}, {"name": "Carol Davis", "email": "carol@vendor-c.com", "phone": "+1555123456"},]
res = insigner_request("POST", "/bulk-sends", json={ "templateId": "tpl_abc123", "name": "Q3 Vendor Agreements", "emailMessage": "Please review and sign your vendor agreement for Q3 2026.", "signers": signers})
data = res["data"]print(f"Bulk send complete: {data['sentCount']}/{data['totalCount']} sent")Reading signers from a CSV
Section titled “Reading signers from a CSV”A common pattern is reading signer data from a CSV file:
import { readFileSync } from 'fs';
function parseCSV(filePath) { const content = readFileSync(filePath, 'utf-8'); const lines = content.trim().split('\n'); const headers = lines[0].split(',').map(h => h.trim());
return lines.slice(1).map(line => { const values = line.split(',').map(v => v.trim()); return Object.fromEntries(headers.map((h, i) => [h, values[i]])); });}
// CSV format: name,email,phoneconst signers = parseCSV('./signers.csv');
const { data } = await insignerFetch('/bulk-sends', { method: 'POST', body: JSON.stringify({ templateId: 'tpl_abc123', name: 'Batch from CSV', signers })});import csv
def read_signers_csv(file_path): with open(file_path) as f: reader = csv.DictReader(f) return [ {"name": row["name"], "email": row["email"], "phone": row.get("phone")} for row in reader ]
# CSV format: name,email,phonesigners = read_signers_csv("./signers.csv")
res = insigner_request("POST", "/bulk-sends", json={ "templateId": "tpl_abc123", "name": "Batch from CSV", "signers": signers})Monitoring progress
Section titled “Monitoring progress”Check the status of a bulk send:
curl -X GET https://app.insigner.co/api/v1/bulk-sends/bs_abc123 \ -H "Authorization: Bearer isk_YOUR_API_KEY"{ "data": { "id": "bs_abc123", "name": "Q3 Vendor Agreements", "status": "completed", "totalCount": 150, "sentCount": 148, "failedCount": 2 }}Or subscribe to webhook events for real-time notifications:
{ "events": ["bulk_send.completed", "bulk_send.failed"]}Rate limits and restrictions
Section titled “Rate limits and restrictions”| Restriction | Limit |
|---|---|
| Maximum signers per bulk send | 500 |
| Time between bulk sends | 5 minutes per organization |
| Concurrent bulk sends | 1 at a time |
If a bulk send is already processing, the API returns 409 Conflict. Wait for it to complete before starting another.