@gtrabanco/newsletter
v0.1.1
Published
Typed, zero-dependency newsletter client for external sites — published to the public npm registry. Workers-safe: uses native `fetch` only, no Node.js SDK.
Readme
@gtrabanco/newsletter
Typed, zero-dependency newsletter client for external sites — published to the public npm registry.
Workers-safe: uses native fetch only, no Node.js SDK.
Wraps the central newsletter service (subscribe + double opt-in + unsubscribe) behind a simple,
stable API so external repos need only a NEWSLETTER_API_KEY and know nothing about the internal
endpoint shape.
Installation
npm install @gtrabanco/[email protected]
# or: bun add @gtrabanco/[email protected]Always pin the exact version (no ^ or ~) — matches this package's convention.
No .npmrc or PAT required — this package is on the public npm registry.
Usage
import { createNewsletterClient } from '@gtrabanco/newsletter';
const newsletter = createNewsletterClient({
apiKey: env.NEWSLETTER_API_KEY,
baseUrl: 'https://gtrabanco.com',
});
// Subscribe a user (double opt-in email is sent automatically)
await newsletter.subscribe('[email protected]', {
language: 'es',
campaign: 'summer-2026',
referrer_domain: 'bingo.gruxon.com',
// Optional: where to land the user after they click the confirm link
confirmRedirectUrl: 'https://bingo.gruxon.com/subscribed',
// Optional: where to redirect after the unsubscribe confirm button is clicked
unsubscribeRedirectUrl: 'https://bingo.gruxon.com/unsubscribed',
});
// Unsubscribe via token from the List-Unsubscribe email header
await newsletter.unsubscribeByToken(token);API
createNewsletterClient(config)
createNewsletterClient({
apiKey: string, // bearer token issued for your site
baseUrl: string, // e.g. 'https://gtrabanco.com'
}): NewsletterClientclient.subscribe(email, opts)
Calls POST /api/v1/newsletter/subscribe. On success returns { ok: true }.
| Option | Type | Required | Notes |
|---|---|---|---|
| language | 'es' \| 'en' \| 'ast' | yes | Confirmation email language |
| campaign | string | no | Acquisition campaign tag |
| referrer_domain | string | no | Referring domain |
| confirmRedirectUrl | string | no | Absolute HTTPS URL — where to send the user after DOI confirmation. Falls back to the source's configured base. |
| unsubscribeRedirectUrl | string | no | Absolute HTTPS URL — where to redirect after unsubscribe confirm. Falls back to source base. |
| sender | { name, email } | no | Forward-compat only — ignored by the server today. Per-API-key sender config is a future dashboard feature. |
client.unsubscribeByToken(token)
Calls POST /api/v1/newsletter/unsubscribe?token=<encoded>. On success returns { ok: true }.
The token comes from the List-Unsubscribe header of outgoing emails.
Errors
import {
isNewsletterHTTPError,
isNewsletterNetworkError,
} from '@gtrabanco/newsletter';
try {
await newsletter.subscribe(email, opts);
} catch (err) {
if (isNewsletterHTTPError(err)) {
// err.status, err.statusText, err.errorCode (e.g. 'RATE_LIMITED', 'ALREADY_SUBSCRIBED')
} else if (isNewsletterNetworkError(err)) {
// fetch() threw — no response received
}
}Auth
apiKey is a bearer token issued per site. Store it in .dev.vars locally and via
wrangler secret put NEWSLETTER_API_KEY for Cloudflare Workers deploys. Never commit it.
Gotchas
senderis accepted in the request schema and forwarded to the server, but the server ignores it and always uses the environment-default Brevo sender. This is intentional forward-compatibility — per-API-key sender config is planned for a future dashboard feature.confirmRedirectUrl/unsubscribeRedirectUrlmust be absolutehttps://URLs. The server rejects non-HTTPS values and falls back to the configured default.unsubscribeByToken()is the only unsubscribe method — email-address-based unsubscribe is an admin action, not exposed via this client.
