@nextengage/sdk
TypeScript icon, indicating that this package has built-in type declarations

0.1.9 • Public • Published

@nextengage/sdk

Official TypeScript SDK for the NextEngage marketing platform.

Install

pnpm add @nextengage/sdk

Usage

import { NextEngage } from "@nextengage/sdk";

// apiKey falls back to the NEXTENGAGE_API_KEY env var, so this works with no args:
const ne = new NextEngage();

// …or pass it explicitly (and optionally override the endpoint for local dev):
// const ne = new NextEngage({
//   apiKey: "ne_...",
//   baseUrl: "http://localhost:3001",
// });

// Upsert a contact (by email) — accepted for async persistence (see below).
// Attributes MERGE: this sets country/plan without touching other attributes;
// send `{ key: null }` to delete a key.
await ne.contacts.upsert({
  email: "ada@example.com",
  attributes: { country: "IN", plan: "pro" },
});

// Track a behavioral event (feeds dynamic segments)
await ne.contacts.track({ email: "ada@example.com", name: "purchased", properties: { amount: 49 } });

// Bulk import
await ne.contacts.bulkImport([
  { email: "a@x.com" },
  { email: "b@x.com", attributes: { vip: true } },
]);

// Create + send a campaign
const tpl = await ne.templates.create({ name: "Promo", subject: "Hi {{ email }}", body: "<p>Sale!</p>" });
const campaign = await ne.campaigns.create({ name: "Spring", templateId: tpl.id, fromEmail: "news@acme.com" });
await ne.campaigns.send(campaign.id);

The API key is scoped to a single project; the SDK resolves the project id automatically from /me.

Async ingest (upsert / track)

On the hosted API, contacts.upsert and contacts.track are accepted onto a durable queue and persisted asynchronously — the request never waits on the database, so it stays fast and resilient even under heavy load or a DB blip. These calls resolve to { accepted: true } (HTTP 202) and do not return the created contact or a contact id — the write happens a moment later. A subsequent read (e.g. contacts.list) may briefly not reflect it yet (eventual consistency).

import { NextEngage, isAccepted } from "@nextengage/sdk";

const result = await ne.contacts.upsert({ email: "ada@example.com" });
if (isAccepted(result)) {
  // Hosted API: queued for async persistence — no entity returned.
} else {
  // Self-hosted with no ingest queue: persisted synchronously, `result` is the Contact.
  console.log(result.id);
}

A self-hosted instance without an ingest queue persists synchronously and returns the entity (Contact / { ok, contactId }) instead — which is why those methods return a union. bulkImport is always synchronous.

Error handling

Failed requests throw NextEngageError with status and parsed body.