A TypeScript client for the Plunk HTTP API.
Targets the legacy Plunk API at https://api.useplunk.com (/v1/* routes). Self-hosted instances using the same API shape are also supported.
Automatically parses JSON-encoded contact data fields in responses.
- A runtime that supports fetch, Buffer and async/await (Node.js >= 18, bun or deno, optionally the browser with a buffer polyfill)
npm install @uninspired/plunk-clientimport { PlunkApiClient } from "@uninspired/plunk-client";
const PLUNK_BASE_URL = "https://api.useplunk.com";
const PLUNK_API_KEY = "sk_your_secret_key";
const plunkApiClient = new PlunkApiClient(PLUNK_BASE_URL, PLUNK_API_KEY);For trackEvent, you can also use a public key (pk_*) instead of your secret key:
const trackClient = new PlunkApiClient(PLUNK_BASE_URL, "pk_your_public_key");const res = await plunkApiClient.trackEvent({
event: "signed_up",
email: "user@example.com",
subscribed: true,
data: {
foo: "bar",
},
});You can provide attachments to the email by providing an array of JavaScript File objects. They will automatically be converted to base64 with the necessary metadata.
const attachment = new File([], "test.txt");
const res = await plunkApiClient.sendEmail({
to: "user@example.com",
subject: "Hello",
body: "Hello, this is a test email.",
subscribed: true,
name: "John Doe",
from: "sender@example.com",
reply: "reply@example.com",
headers: {
"X-Custom-Header": "Test",
},
attachments: [attachment],
});
// Recipient address is on the nested contact object
const recipient = res.emails[0]?.contact.email;Campaign style accepts "PLUNK" or "HTML". "PLUNK" is sent to the API as "SANS".
const res = await plunkApiClient.createCampaign({
subject: "Hello",
body: "Hello, this is a test email.",
recipients: ["user@example.com"],
style: "PLUNK",
});await plunkApiClient.sendCampaign("[CAMPAIGN_ID]", {
live: true, // Should the campaign be sent to the recipients
delay: 5, // in minutes
});const res = await plunkApiClient.updateCampaign("[CAMPAIGN_ID]", {
subject: "Hello",
body: "Hello, this is a test email.",
recipients: ["user@example.com"],
style: "PLUNK",
});const res = await plunkApiClient.deleteCampaign("[CAMPAIGN_ID]");interface ContactData {
foo: string;
}
const res = await plunkApiClient.getContactById<ContactData>("[CONTACT_ID]");interface ContactData {
foo: string;
}
const res = await plunkApiClient.getAllContacts<ContactData>();const res = await plunkApiClient.getNumberOfContacts();interface ContactData {
foo: string;
}
const res = await plunkApiClient.createContact<ContactData>({
email: "user@example.com",
subscribed: true,
data: {
foo: "bar",
},
});// Subscribe contact by ID
const res = await plunkApiClient.subscribeContact({ id: "[CONTACT_ID]" });
// Subscribe contact by email
const res = await plunkApiClient.subscribeContact({
email: "user@example.com",
});// Unsubscribe contact by ID
const res = await plunkApiClient.unsubscribeContact({ id: "[CONTACT_ID]" });
// Unsubscribe contact by email
const res = await plunkApiClient.unsubscribeContact({
email: "user@example.com",
});interface ContactData {
foo: string;
}
const res = await plunkApiClient.updateContact<ContactData>({
id: "[CONTACT_ID]",
subscribed: true,
data: { foo: "bar" },
});const res = await plunkApiClient.deleteContact({ id: "[CONTACT_ID]" });bun run build # Build ESM, CJS, and type declarations
bun run typecheck # Type-check src and tests
bun test # Run integration tests against the live APITests run against the real Plunk API. Copy .env.example to .env and fill in your credentials:
cp .env.example .env| Variable | Description |
|---|---|
PLUNK_SECRET_KEY |
Secret API key (sk_*) for most endpoints |
PLUNK_PUBLIC_KEY |
Public API key (pk_*) for trackEvent tests |
PLUNK_BASE_URL |
API base URL (https://api.useplunk.com) |
PLUNK_TEST_EMAIL |
Inbox used for send/track tests |
PLUNK_TEST_FROM |
Verified sender address for email tests |
Any request or response that contains a "data" field can have its type enforced by providing a type argument to the respective method.
Note: The data is not validated, it is simply typed.
interface ContactData {
foo: string;
bar?: string;
}
const res = await plunkApiClient.getContactById<ContactData>("[CONTACT_ID]");
// res.data will be of type ContactDataThis will throw a TypeScript error:
interface ContactData {
foo: string;
}
const res = await plunkApiClient.trackEvent<ContactData>({
event: "signed_up",
email: "user@example.com",
data: {
bar: "bar",
},
});