{"_id":"unitpost","_rev":"6-5e01caaf8faa6663a9ee789b46db917a","name":"unitpost","dist-tags":{"latest":"0.4.0"},"versions":{"0.0.0":{"name":"unitpost","version":"0.0.0","keywords":["unitpost","email","transactional-email","placeholder"],"license":"MIT","_id":"unitpost@0.0.0","maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"homepage":"https://unitpost.com","dist":{"shasum":"c2594f345dec7b4d5a5fd2ddb9fd02647edac936","tarball":"https://registry.npmjs.org/unitpost/-/unitpost-0.0.0.tgz","fileCount":2,"integrity":"sha512-OzI+vTuLp8LbagWLRvxIIBQdZgD5uaS2TkrBbtWlCc0CHYO4dpRy68NFme9OXzShkq1DG1ZgLpKVut/+up4UyA==","signatures":[{"sig":"MEYCIQDVzPS9HW/lWEDbeHCICTaIWiu3BtVi6tGfVWl2865EfwIhANvXsPbgn9pZn9ewQtbQnXBitF+GvXCttdLqr4oHeLTE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":824},"gitHead":"24801e7c62683ca2a8afcf30e173b8ee663e0149","_npmUser":{"name":"docreator","email":"mike@workreactor.com"},"_npmVersion":"10.9.3","description":"Name reserved for Unitpost — the official packages are published under the @unitpost scope (e.g. @unitpost/email).","directories":{},"_nodeVersion":"22.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/unitpost_0.0.0_1782503882879_0.19723701686971995","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"unitpost","version":"0.1.0","keywords":["unitpost","email","transactional-email","sdk","api"],"license":"MIT","_id":"unitpost@0.1.0","maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"homepage":"https://www.unitpost.com/docs","bugs":{"url":"https://github.com/unitpostcom/unitpost/issues"},"dist":{"shasum":"afcfc0545c6c3abebf9037f763dd2f4627e2adff","tarball":"https://registry.npmjs.org/unitpost/-/unitpost-0.1.0.tgz","fileCount":8,"integrity":"sha512-NSuhAK8A39cnRYCVt3DXhn1eNQ9hjEgis+R7mxEq0EggZvnDAm976vfAX0Q3keXMqucH6aPSO/uKNL1BE6WxsQ==","signatures":[{"sig":"MEYCIQDNQyIX32NZ1mkfgtfgYvwsgJEiw4NBCN7F2UVF4JWGcAIhANYWvt/ez8J9g75xQud44AaoCjtw2hh3QrDN2a78wV9C","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":405658},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"9d3433050e646984b1ae4270adc16afc77128a95","scripts":{"test":"node --import tsx --test $(find src -name '*.test.ts')","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"docreator","email":"mike@workreactor.com"},"repository":{"url":"git+https://github.com/unitpostcom/unitpost.git","type":"git","directory":"packages/sdk-node"},"_npmVersion":"10.8.2","description":"Official Unitpost SDK for Node.js — send email and manage contacts, segments, campaigns, templates, brand kits, domains, suppressions, webhooks, and usage.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","tsup":"^8.5.0","typescript":"^5.9.2"},"_npmOperationalInternal":{"tmp":"tmp/unitpost_0.1.0_1785147348538_0.34950742583952477","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"unitpost","version":"0.2.0","keywords":["unitpost","email","transactional-email","sdk","api"],"license":"MIT","_id":"unitpost@0.2.0","maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"homepage":"https://www.unitpost.com/docs","bugs":{"url":"https://github.com/unitpostcom/unitpost/issues"},"dist":{"shasum":"0742535d08d507ae355dc8ce325681f1f3e5147f","tarball":"https://registry.npmjs.org/unitpost/-/unitpost-0.2.0.tgz","fileCount":8,"integrity":"sha512-BP2nCE78oLWplKFwQdqCduJR+1Bv7fujqPNHFzSPXCi44hMtn03Xy3dKfT59HqxDvQm68ksXqBlZckHf5vmvSA==","signatures":[{"sig":"MEQCIAPjZMF2wH6P1TVf7iPj+ZVTN4eilja8v919ggBWGtS8AiAcXVl7eTs1XMKF5dBmlMpVf+yzBrUUblpvdX/5GtG+8A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":407637},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"447bac1c4ff23c6f1df8fd2d502c8a55a48efbea","scripts":{"test":"node --import tsx --test $(find src -name '*.test.ts')","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"docreator","email":"mike@workreactor.com"},"repository":{"url":"git+https://github.com/unitpostcom/unitpost.git","type":"git","directory":"packages/sdk-node"},"_npmVersion":"10.8.2","description":"Official Unitpost SDK for Node.js — send email and manage contacts, segments, campaigns, templates, brand kits, domains, suppressions, webhooks, and usage.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","tsup":"^8.5.0","typescript":"^5.9.2"},"_npmOperationalInternal":{"tmp":"tmp/unitpost_0.2.0_1785485180094_0.15505856419790098","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"unitpost","version":"0.2.1","keywords":["unitpost","email","transactional-email","sdk","api"],"license":"MIT","_id":"unitpost@0.2.1","maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"homepage":"https://www.unitpost.com/docs","bugs":{"url":"https://github.com/unitpostcom/unitpost/issues"},"dist":{"shasum":"5ed4dd2119bc108d95ec2069b0d2c5cb17491e97","tarball":"https://registry.npmjs.org/unitpost/-/unitpost-0.2.1.tgz","fileCount":8,"integrity":"sha512-iHJLHpW8jtxXL5kUSZwe/neobUkPhNusMlLiV2UxY22+onLbZACOdPm+Z52RDoT5BYUpgfEpwVgqCJ6o1Xx8lA==","signatures":[{"sig":"MEYCIQDzImNOvrZqaoiq/KszZ3eKfDSUYlpLN9Uuxlip9xEizwIhAJJeKQRWqkk9gyZhX2SSyu73Xfm++NjfnBJH4mXCceWb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":407637},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"68f8a3f85e8d748fc6b97084a6199b0d8ed6ed2f","scripts":{"test":"node --import tsx --test $(find src -name '*.test.ts')","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"docreator","email":"mike@workreactor.com"},"repository":{"url":"git+https://github.com/unitpostcom/unitpost.git","type":"git","directory":"packages/sdk-node"},"_npmVersion":"10.8.2","description":"Official Unitpost SDK for Node.js — send email and manage contacts, segments, campaigns, templates, brand kits, domains, suppressions, webhooks, and usage.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","tsup":"^8.5.0","typescript":"^5.9.2"},"_npmOperationalInternal":{"tmp":"tmp/unitpost_0.2.1_1785485838431_0.5191301239117057","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"unitpost","version":"0.3.0","keywords":["unitpost","email","transactional-email","sdk","api"],"license":"MIT","_id":"unitpost@0.3.0","maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"homepage":"https://www.unitpost.com/docs","bugs":{"url":"https://github.com/unitpostcom/unitpost/issues"},"dist":{"shasum":"0914b2811ae47db0fee2d87ca6886ac91c2571af","tarball":"https://registry.npmjs.org/unitpost/-/unitpost-0.3.0.tgz","fileCount":8,"integrity":"sha512-Nqe7noiAxfIIyC13GlXW+3Lr/NC6WkAM16+OBU12c5u7hvZsMZaqrH4mVtMaG8PbAn4T5sCzzRSJgNSWSJf1yA==","signatures":[{"sig":"MEYCIQDteSrzbvAva3loEX7gCzWgmUuppBkW3J73XoAsamgKUwIhALGRYv+bZK0mOQ2mti9WLf3QIiP3+Hnak6M31doYY+VD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":318284},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"85b26ba4663ebe9cf2be0c2835afa15b1599b88b","scripts":{"test":"node --import tsx --test $(find src -name '*.test.ts')","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"docreator","email":"mike@workreactor.com"},"repository":{"url":"git+https://github.com/unitpostcom/unitpost.git","type":"git","directory":"packages/sdk-node"},"_npmVersion":"10.8.2","description":"Official Unitpost SDK for Node.js — send email and manage contacts, segments, campaigns, templates, brand kits, domains, suppressions, webhooks, and usage.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","tsup":"^8.5.0","typescript":"^5.9.2"},"_npmOperationalInternal":{"tmp":"tmp/unitpost_0.3.0_1787947081797_0.4815142463820541","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"_id":"unitpost@0.4.0","bugs":{"url":"https://github.com/unitpostcom/unitpost/issues"},"dist":{"shasum":"de0d232b50ac942b69c0ec4956b420a85a7ee746","tarball":"https://registry.npmjs.org/unitpost/-/unitpost-0.4.0.tgz","fileCount":8,"integrity":"sha512-Wp4PihD2WEboM5xNJfUT8CjelObDvMAWHZmHWqCmS3W/2+bUtllJ0fRNjZXY1E3BRJeIyX0Rw+miuhBEgo74zg==","signatures":[{"sig":"MEYCIQDwUhaivuqNpRtdIP82HDMT7+7knGu2dHnka6X8j8vOsAIhAMr6ygmkFMaEj9xNVT7CH1BuAgv14DxoPvatZ1bCM8yR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC/M+hSYxXAPGD4M0iBGDviLHRZj4h61A2U7VnVbVrycQIgFbqbmp/5R15s06/SYLSqoiAfmCQ8sue1DLu5TOGuQ8A="}],"unpackedSize":515273},"main":"./dist/index.cjs","name":"unitpost","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"404161012edfaa0734bfcaac55b78f6645923315","license":"MIT","scripts":{"test":"node --import tsx ../../tools/node-test.mjs","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"version":"0.4.0","_npmUser":{"name":"docreator","email":"mike@workreactor.com"},"homepage":"https://www.unitpost.com/docs","keywords":["unitpost","email","transactional-email","sdk","api"],"repository":{"url":"git+https://github.com/unitpostcom/unitpost.git","type":"git","directory":"packages/sdk-node"},"_npmVersion":"11.19.1","description":"Official Unitpost SDK for Node.js — send email and manage contacts, segments, campaigns, templates, brand kits, domains, suppressions, webhooks, and usage.","directories":{},"maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"sideEffects":false,"_nodeVersion":"24.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.12","tsup":"^8.5.0","typescript":"^5.9.2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/unitpost_0.4.0_1792990442171_0.7938708346179353"}}},"time":{"created":"2026-06-26T19:58:02.722Z","modified":"2026-10-26T04:54:02.465Z","0.0.0":"2026-06-26T19:58:03.009Z","0.1.0":"2026-07-27T10:15:48.685Z","0.2.0":"2026-07-31T08:06:20.248Z","0.2.1":"2026-07-31T08:17:18.596Z","0.3.0":"2026-08-28T19:58:01.948Z","0.4.0":"2026-10-26T04:54:02.281Z"},"bugs":{"url":"https://github.com/unitpostcom/unitpost/issues"},"license":"MIT","homepage":"https://www.unitpost.com/docs","keywords":["unitpost","email","transactional-email","sdk","api"],"repository":{"url":"git+https://github.com/unitpostcom/unitpost.git","type":"git","directory":"packages/sdk-node"},"description":"Official Unitpost SDK for Node.js — send email and manage contacts, segments, campaigns, templates, brand kits, domains, suppressions, webhooks, and usage.","maintainers":[{"name":"docreator","email":"mike@workreactor.com"}],"readme":"# unitpost\n\nOfficial [Unitpost](https://www.unitpost.com) SDK for Node.js. Send email and manage\ncontacts, segments, campaigns, templates, domains, suppressions, and webhooks.\n\n## Install\n\n```bash\nnpm install unitpost\n```\n\nRequires Node.js 18+ (uses the built-in `fetch`).\n\n## Quick start\n\n```ts\nimport { Unitpost } from \"unitpost\";\n\nconst unitpost = new Unitpost(process.env.UNITPOST_API_KEY);\n\nconst { data, error } = await unitpost.email.send({\n  from: \"Acme <you@yourdomain.com>\", // bare address works too\n  to: \"customer@example.com\",\n  subject: \"Hello\",\n  html: \"<p>It works!</p>\",\n});\n\nif (error) {\n  console.error(error.code, error.message);\n} else {\n  console.log(\"sent\", data.id);\n}\n```\n\nEvery method returns `{ data, error }` — an API-level failure populates `error`\n(a typed `UnitpostError`) instead of throwing, so you never need a `try/catch`\naround a normal request.\n\n## Authentication\n\nPass the key directly, or set `UNITPOST_API_KEY` and construct with no argument:\n\n```ts\nconst unitpost = new Unitpost(); // reads process.env.UNITPOST_API_KEY\n```\n\nCreate a key at [unitpost.com → Settings → API keys](https://www.unitpost.com).\nOptions: `new Unitpost({ apiKey, baseUrl, timeout, fetch, headers, maxRetries, retryBaseDelay, maxRetryDelay })`.\n\n## Client surface\n\n| Accessor | Covers |\n| --- | --- |\n| `email` | Send, batch, list, get, update, stats, inbound (`received*`) |\n| `email.topics` | Topics + contact topic prefs |\n| `email.campaigns` | Draft, schedule, send, pause/resume |\n| `email.templates` | Template CRUD |\n| `email.domains` | Domains + verify |\n| `sms` | Send, get, list, `brands()`, `numbers()`, contact SMS consent. Available on paid plans: on the free plan `send` returns a `403` with code `limit_reached`, while the reads keep working. |\n| `contacts` | CRUD, import jobs |\n| `contactFields` | Custom field definitions |\n| `segments` | Segments + membership |\n| `brandKits` | Brand kit |\n| `webhooks` | Endpoints + `verify()` |\n| `apiKeys` | API key management |\n| `suppressions` | Suppression list |\n| `usage` | Billing-period usage snapshot |\n\n## Pagination\n\nList endpoints are cursor-paginated. Use `list()` for one page or `listAll()`\nto async-iterate every row:\n\n```ts\nfor await (const contact of unitpost.contacts.listAll()) {\n  console.log(contact.email);\n}\n```\n\n## Suppressions\n\nThe suppression list holds addresses that are excluded from every send — single,\nbatch, and campaign, including cc/bcc — case-insensitively. Hard bounces and spam\ncomplaints are added automatically; you can also add your own:\n\n```ts\n// Suppress one address, or many in a single call (idempotent — re-adding is a no-op).\nawait unitpost.suppressions.create({ email: \"bounced@example.com\", reason: \"manual\" });\nawait unitpost.suppressions.create({ emails: [\"a@example.com\", \"b@example.com\"] });\n\n// Look one up by id or email; list your own; un-suppress.\nconst { data } = await unitpost.suppressions.get(\"bounced@example.com\");\nfor await (const s of unitpost.suppressions.listAll()) console.log(s.email, s.reason);\nawait unitpost.suppressions.delete(\"bounced@example.com\");\n```\n\n`reason` accepts `manual`, `import`, or `api` — the engine-written `bounce` and\n`complaint` reasons are read-only. Unitpost-wide (`platform`) entries are visible\nbut can't be removed via the API.\n\n## Verifying webhooks\n\nDeliveries are svix-compatible. Verify the raw request body against your\nendpoint's signing secret:\n\n```ts\nimport { verifyWebhook } from \"unitpost\";\n\nconst event = verifyWebhook({\n  payload: rawBody,            // the raw request body string\n  secret: process.env.UNITPOST_WEBHOOK_SECRET,\n  headers: req.headers,\n});\n```\n\nYou can also call it from the client (Resend-style alias):\n\n```ts\nconst event = unitpost.webhooks.verify({ payload: rawBody, secret, headers: req.headers });\n```\n\n## Receive a text and answer it\n\nUS toll-free, 10DLC and Canadian numbers take replies (`two_way: true` on\n`sms.numbers()`). Subscribe a webhook to `sms.received`, skip STOP and texts\nUnitpost already answered, read the conversation with `participant`, and answer\nwithout `from` so the reply leaves from the number they texted.\n\n```ts\nimport { Unitpost, verifyWebhook } from \"unitpost\";\n\nconst unitpost = new Unitpost(process.env.UNITPOST_API_KEY);\n\n// Your webhook endpoint, subscribed to sms.received. Pass the RAW body.\nexport async function onWebhook(rawBody: string, headers: Record<string, string>) {\n  const event = verifyWebhook<{ type: string; data: SmsReceived }>({\n    payload: rawBody,\n    secret: process.env.UNITPOST_WEBHOOK_SECRET!, // whsec_…\n    headers,\n  });\n  if (event.type !== \"sms.received\") return;\n  const reply = event.data;\n  if (reply.keyword === \"OPT_OUT\" || reply.auto_replied) return; // STOP, or already answered\n\n  // The whole conversation with this person, both directions, newest first.\n  const { data: history } = await unitpost.sms.list({ participant: reply.from, limit: 20 });\n  const answer = await yourAgent(history?.data ?? [], reply.body ?? \"\");\n\n  // No `from`: the answer goes out from the number they texted.\n  await unitpost.sms.send({ to: reply.from, body: answer });\n}\n\ntype SmsReceived = {\n  sms_id: string;\n  from: string;\n  to: string;\n  body: string | null; // empty when the reply carried no text\n  keyword: \"OPT_OUT\" | \"OPT_IN\" | \"HELP\" | null;\n  auto_replied: boolean;\n  in_reply_to: string | null;\n  contact_id: string | null;\n  received_at: string | null; // order a conversation by this\n  created_at: string | null;\n};\n```\n\n## Idempotency\n\n`email.send` and `email.batch` are safe to retry by default: if you don't pass\nan idempotency key, the SDK generates one for you so an automatic retry can never\nsend twice. Pass your own to dedupe across separate calls (e.g. a user\ndouble-clicks \"send\"):\n\n```ts\nawait unitpost.email.send({ ... }, { idempotencyKey: crypto.randomUUID() });\nawait unitpost.email.batch([ ... ], { idempotencyKey: crypto.randomUUID() });\n```\n\n> The server dedupes on `(workspace, idempotency key)` for 24h and replays the\n> original result instead of re-sending — for a single send that's the email id,\n> for a batch the full list envelope.\n\n## Retries\n\nTransient failures are retried automatically: `429`, `5xx`, and transport errors\n(timeouts / network) retry up to `maxRetries` times (default `2`). A `429`/`503`\n`Retry-After` is honored; otherwise the client uses exponential backoff with full\njitter. Client errors (`401`/`403`/`404`/`409`/`422`) are never retried.\n\nOnly requests that are **safe to replay** are retried: `GET`s and writes that\ncarry an idempotency key (which `email.send` and `email.batch` always do — see\nabove). Any other keyless write is never auto-retried.\n\n```ts\n// Defaults shown; set maxRetries: 0 to disable.\nconst unitpost = new Unitpost({ maxRetries: 2, retryBaseDelay: 500, maxRetryDelay: 20_000 });\n```\n\n## Type-safety and the API contract\n\nRequest/response types are generated 1:1 from the public OpenAPI spec and\nexported under `Models`. The SDK plumbing is regenerated from that spec and\nCI-gated, so the SDK never silently drifts from the API.\n\n## Resources\n\n| | |\n| --- | --- |\n| Docs + API reference | https://www.unitpost.com/docs |\n| Product guides | https://www.unitpost.com/guides |\n| SMTP | https://www.unitpost.com/docs/smtp |\n| OpenAPI JSON | https://www.unitpost.com/api/v1/openapi.json |\n| LLM index | https://www.unitpost.com/llms.txt |\n| Dashboard / API keys | https://www.unitpost.com |\n| Email components (`@unitpost/email`) | https://www.unitpost.com/components |\n| Template gallery | https://www.unitpost.com/templates/gallery |\n| Playground | https://www.unitpost.com/playground |\n| Migration Assistant | https://www.unitpost.com/migration |\n| MCP + Agent Skills | https://www.unitpost.com/docs/ai/mcp · https://www.unitpost.com/docs/ai/skills |\n| Support | support@unitpost.com |\n\n## License\n\nMIT\n","readmeFilename":"README.md"}