@robasedev/node
v0.1.0
Published
Official Robase.dev Node.js / TypeScript SDK — Resend-compatible API shape.
Downloads
82
Maintainers
Readme
@robasedev/node
Official Node.js / TypeScript SDK for Robase.dev — transactional email for Nigerian developers, API-compatible with Resend.
Install
npm install @robasedev/node
# or
pnpm add @robasedev/nodeQuickstart
import { Robase } from '@robasedev/node';
const robase = new Robase({ apiKey: process.env.ROBASE_API_KEY! });
const email = await robase.emails.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Welcome to Acme',
html: '<h1>Thanks for signing up</h1>',
text: 'Thanks for signing up'
});
console.log(email.id);Configuration
new Robase({
apiKey: 'sk_live_...',
baseUrl: 'https://api.robase.dev', // override for self-hosted
timeoutMs: 30_000,
maxRetries: 2 // 5xx / 429 / network errors
});Sending
Single
await robase.emails.send({
from: '[email protected]',
to: ['[email protected]', '[email protected]'],
cc: '[email protected]',
subject: 'Hi',
html: '<p>…</p>',
text: 'fallback',
reply_to: '[email protected]',
headers: { 'X-Campaign': 'spring' },
tags: { campaign: 'spring', variant: 'A' },
tracking: { opens: true, clicks: true },
attachments: [
{
filename: 'invoice.pdf',
content: Buffer.from(pdfBytes).toString('base64'),
content_type: 'application/pdf'
}
],
// Delay send until a future time (ISO 8601).
scheduled_at: new Date(Date.now() + 60_000).toISOString(),
// De-dup repeat attempts within 24h.
idempotency_key: 'welcome-user-42'
});Batch
const { data } = await robase.emails.batch([
{ from: '[email protected]', to: '[email protected]', subject: 'hi', text: 'one' },
{ from: '[email protected]', to: '[email protected]', subject: 'hi', text: 'two' }
]);
for (const item of data) {
if ('error' in item) console.error('failed:', item.error.type);
else console.log('queued:', item.id);
}Retrieve + cancel
const details = await robase.emails.get('em_123');
console.log(details.status, details.events);
// Queued / scheduled only — throws ValidationError otherwise.
await robase.emails.cancel('em_123');Domains
const { domain, dns_records } = await robase.domains.create('acme.com');
console.log(dns_records); // configure these at your DNS providerWebhook signature verification
Every webhook delivery carries a Robase-Signature header. Verify it before trusting the body.
import express from 'express';
import { verifyWebhookSignature } from '@robasedev/node';
const app = express();
app.post('/webhooks/robase', express.raw({ type: 'application/json' }), (req, res) => {
try {
verifyWebhookSignature({
payload: req.body, // raw Buffer — NOT JSON.parsed
header: req.header('Robase-Signature')!,
secret: process.env.ROBASE_WEBHOOK_SECRET!
});
} catch (err) {
return res.status(400).send(String(err));
}
const event = JSON.parse(req.body.toString());
// … handle event.type (email.delivered, email.bounced, …)
res.send('ok');
});Errors
Every failure throws a subclass of RobaseError you can catch by type:
| Class | HTTP |
|---|---|
| AuthenticationError | 401 |
| NotFoundError | 404 |
| ValidationError | 422 (use err.type to branch on recipient_suppressed, from_domain_not_verified, etc.) |
| RateLimitError | 429 (err.retryAfter in seconds) |
| ServerError | 5xx |
The SDK retries ServerError, RateLimitError, and network failures with exponential backoff + jitter.
License
MIT.
