-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbulk-send.js
More file actions
103 lines (89 loc) · 3.27 KB
/
bulk-send.js
File metadata and controls
103 lines (89 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Send postcards to a CSV list of recipients via the Postcard.bot bulk API
// Usage: POSTCARDBOT_API_KEY=pk_live_your_key node bulk-send.js customers.csv
//
// CSV format (first row = headers):
// name,address_line1,city,state,zip,country
// Jane Doe,123 Main St,San Francisco,CA,94102,US
//
// The message supports {{name}} which is replaced with each recipient's first name.
const fs = require("fs");
const path = require("path");
const API_KEY = process.env.POSTCARDBOT_API_KEY;
const BASE_URL = process.env.POSTCARDBOT_API_URL || "https://postcard.bot";
if (!API_KEY) {
console.error("Set POSTCARDBOT_API_KEY environment variable");
process.exit(1);
}
const csvFile = process.argv[2];
if (!csvFile) {
console.error("Usage: node bulk-send.js <customers.csv>");
console.error("\nSee sample.csv for the expected format.");
process.exit(1);
}
function parseCSV(filePath) {
const content = fs.readFileSync(filePath, "utf-8");
const lines = content.trim().split("\n");
const headers = lines[0].split(",").map((h) => h.trim().toLowerCase());
return lines.slice(1).map((line) => {
const values = line.split(",").map((v) => v.trim());
const row = {};
headers.forEach((h, i) => (row[h] = values[i] || ""));
return {
name: row.name || "",
address_line1: row.address_line1 || row.address || "",
address_line2: row.address_line2 || "",
city: row.city || "",
state: row.state || "",
zip: row.zip || row.postal_code || "",
country: row.country || "US",
};
});
}
async function bulkSend() {
const recipients = parseCSV(csvFile);
console.log(`Loaded ${recipients.length} recipients from ${csvFile}`);
if (recipients.length === 0) {
console.error("No recipients found in CSV");
process.exit(1);
}
// Show first few recipients
console.log("\nFirst recipients:");
recipients.slice(0, 3).forEach((r) => {
console.log(` ${r.name}, ${r.city} ${r.state}`);
});
if (recipients.length > 3) console.log(` ... and ${recipients.length - 3} more`);
const response = await fetch(`${BASE_URL}/api/v1/postcards/bulk`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
recipients,
from: {
name: "Your Business Name",
address_line1: "456 Oak Ave",
city: "New York",
state: "NY",
zip: "10001",
},
// {{name}} is replaced with each recipient's first name
message: "Hi {{name}}, thank you for being a valued customer! We appreciate your business.",
image_url: "https://images.unsplash.com/photo-1501594907352-04cda38ebc29?w=1875",
}),
});
const data = await response.json();
if (!response.ok) {
console.error("\nError:", data.error);
if (data.details) console.error("Details:", data.details);
process.exit(1);
}
console.log("\nBulk job queued!");
console.log(` Bulk ID: ${data.bulk_id}`);
console.log(` Total recipients: ${data.total}`);
console.log(` Reserved cost: $${data.total_cost.toFixed(2)}`);
console.log(` Status: ${data.status}`);
console.log(`\nCards will be processed in background batches (~25/minute).`);
console.log(`Check progress: node check-status.js ${data.bulk_id}`);
}
bulkSend().catch(console.error);