Copy
npm i @fluxomail/sdk
Copy
import { Fluxomail } from '@fluxomail/sdk'
import { readFile } from 'node:fs/promises'
const fm = new Fluxomail({ apiKey: process.env.FLUXOMAIL_API_KEY })
await fm.sends.send({
to: 'user@example.com',
subject: 'Hello',
content: 'Hi there',
htmlContent: '<p>Hi there</p>',
cc: ['c1@example.com'],
bcc: 'b1@example.com',
attachments: [
{
filename: 'report.pdf',
content: await readFile('report.pdf'), // Buffer | Uint8Array | string | Blob (browser)
contentType: 'application/pdf'
}
],
idempotencyKey: 'send-123'
})
- Use
apiKeyserver-side only. In browsers, mint short‑lived tokens on your server. - The SDK maps
content/htmlContentto the public API and encodes attachments to base64 (supportsBlob/Filein browsers).
Copy
const { data, meta } = await fm.events.listWithMeta({ limit: 1 })
console.log(meta.requestId)
Copy
const fm = new Fluxomail({ apiKey, retry: { maxAttempts: 5, retriableStatuses: [408, 429], baseDelayMs: 200, maxDelayMs: 1500 } })
Copy
// Override timeout and retry only for this call
await fm.events.list({ limit: 1, timeoutMs: 2000, retry: { maxAttempts: 5, baseDelayMs: 100 } })
Copy
import { Fluxomail } from '@fluxomail/sdk'
// Get a short-lived token from your server (Next.js example route: /api/fluxomail/token)
const { token } = await fetch('/api/fluxomail/token', { method: 'POST' }).then(r => r.json())
const fm = new Fluxomail({ token, getToken: async () => {
// Auto-refresh tokens for REST calls after a 401
const r = await fetch('/api/fluxomail/token', { method: 'POST' })
return (await r.json()).token
}})
// Subscribe to realtime events, persisting a checkpoint
const sub = fm.events.subscribe({ types: ['email.*'], checkpoint: {
get: () => localStorage.getItem('fluxo:lastEventId') || undefined,
set: (id) => localStorage.setItem('fluxo:lastEventId', id)
}}, (evt) => {
console.log('event', evt)
})
// Later: sub.close()
Copy
// Iterate a send's timeline (auto-paging)
for await (const evt of fm.timelines.iterate({ sendId: 'send_abc123', limit: 100 })) {
console.log('timeline', evt)
}
// Abort a long-running list
const ac = new AbortController()
const p = fm.events.list({ types: ['email.*'], limit: 1000, signal: ac.signal })
ac.abort()
Copy
export type SendParams = {
baseUrl?: string;
apiKey: string;
to: string; subject: string; content: string; htmlContent?: string;
idempotencyKey?: string; policyKey?: string;
};
export async function sendEmail(p: SendParams) {
const base = p.baseUrl || 'https://api.fluxomail.com';
const res = await fetch(`${base}/api/v1/emails/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${p.apiKey}`,
...(p.idempotencyKey ? { 'Idempotency-Key': p.idempotencyKey } : {}),
},
body: JSON.stringify({ to: p.to, subject: p.subject, content: p.content, htmlContent: p.htmlContent, policyKey: p.policyKey })
});
const body = await res.json();
if (!res.ok) throw Object.assign(new Error(body?.message || body?.error || 'Request failed'), { response: body });
return { data: body, requestId: res.headers.get('Fluxomail-Request-Id') };
}
Copy
import os, uuid, requests
def send_email(api_key: str, to: str, subject: str, content: str, html: str | None = None, idem: str | None = None):
base = 'https://api.fluxomail.com'
headers = { 'Authorization': f'Bearer {api_key}' }
if idem: headers['Idempotency-Key'] = idem
r = requests.post(f"{base}/api/v1/emails/send", headers=headers, json={
'to': to, 'subject': subject, 'content': content, 'htmlContent': html
})
r.raise_for_status()
return { 'data': r.json(), 'request_id': r.headers.get('Fluxomail-Request-Id') }
- Download the OpenAPI spec to generate clients for other languages:
/api-reference/openapi.fluxomail.json
Copy
// When you specify concrete event types, the handler is narrowed accordingly
fm.events.subscribe({ types: ['email.delivered', 'email.opened'] }, (evt) => {
// evt is EmailEventEnvelope<'email.delivered' | 'email.opened'>
})
Copy
const sub = fm.events.subscribe({
types: ['email.*'],
onOpen: () => console.log('connected'),
onError: (e) => console.log('sse error', e),
onReconnect: (attempt, delay) => console.log('reconnecting', { attempt, delay }),
backoff: { baseDelayMs: 100, maxDelayMs: 1000 },
}, (evt) => {/* ... */})
Copy
// Create and render a template
const t = await fm.templates.create({ name: 'Welcome', subject: 'Hi {{name}}', htmlContent: '<h1>Hi {{name}}</h1>' })
const rendered = await fm.templates.render(t.id, { variables: { name: 'Pat' } })
// Manage
await fm.templates.update(t.id, { subject: 'Hello {{name}}' })
const list = await fm.templates.list({ limit: 10 })
await fm.templates.delete(t.id)
Copy
import { webhooks } from '@fluxomail/sdk'
export async function handler(req, res) {
const raw = await getRawBody(req) // raw string
const ok = webhooks.verifyHmacSignature(raw, req.headers, { secret: process.env.FLUXOMAIL_WEBHOOK_SECRET! })
if (!ok) return res.status(401).end('invalid signature')
const out = webhooks.verifyAndParse(raw, req.headers, { secret: process.env.FLUXOMAIL_WEBHOOK_SECRET! })
for (const evt of out.events) {
// handle
}
res.status(200).end('ok')
}
