Senviok SDK
Senviok provides official SDKs that wrap our REST API, giving you a type-safe, idiomatic way to send emails, SMS, and WhatsApp messages. SDKs handle authentication, error handling, and serialization — so you can focus on building.
Quick Start
Send your first email in under 30 seconds.
1Install the SDK
npm install senviok2Initialize the client
import { Senviok } from 'senviok';
const senviok = new Senviok('svk_live_your_api_key');3Send an email
const { id } = await senviok.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Hello from Senviok',
html: '<h1>Welcome!</h1><p>You\'re all set.</p>'
});
console.log('Sent!', id); // msg_01HZ8...Official SDKs
We're building SDKs for every popular language. Install the one for your stack and start sending in minutes.
gem install senviokimplementation 'com.senviok:senviok-java'dotnet add package SenviokAuthentication
All requests are authenticated with a Bearer API key. Generate keys from your Dashboard under Settings → API Keys. Keys are prefixed with svk_live_.
svk_live_your_api_key
import { Senviok } from 'senviok';
// Initialize with your API key
const senviok = new Senviok('svk_live_your_api_key');
// Or with a custom base URL
const senviok = new Senviok('svk_live_your_api_key', {
BASE: 'https://your-custom-api.example.com'
});Send Email
Send transactional emails with HTML/text body, templates, CC/BCC, and unsubscribe headers. Every send returns a unique message ID for tracking.
Default Sender: If you haven't verified a custom domain, use onboarding@senviok.live as your from address to get started.
Basic Email
await senviok.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome to Acme!',
html: '<h1>Hello!</h1><p>Welcome aboard.</p>',
text: 'Hello! Welcome aboard.'
});Expected Response
{
"id": "msg_01HZ8a3b4c5d6e7f"
}Asynchronous Delivery Pipeline
An HTTP 200 OK response with a message ID confirms that your email was validated and accepted into Senviok's high-speed dispatch queue.
Because email delivery over SMTP involves remote receiving mail servers, final delivery status (e.g. delivered, rejected, bounced, opened) is handled asynchronously. To track delivery confirmations and handle bounces programmatically in real time, configure or check .
With Template
await senviok.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome {{name}}!',
templateId: 'tmpl_welcome',
templateData: { name: 'John', company: 'Acme' }
});With CC, BCC, Reply-To
await senviok.emails.send({
from: 'hello@yourdomain.com',
fromName: 'Acme Support',
to: 'user@example.com',
subject: 'Your Invoice',
html: '<p>Please find your invoice attached.</p>',
cc: 'manager@acme.com',
bcc: 'records@acme.com',
replyTo: 'support@acme.com',
addUnsubscribeFooter: true,
addListUnsubscribeHeader: true
});Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| from | string | Yes | Sender email address |
| to | string | Yes | Recipient email address |
| subject | string | Yes | Email subject line |
| html | string | No* | HTML body content |
| text | string | No* | Plain text body content |
| fromName | string | No | Sender display name |
| cc | string | No | CC recipient(s) |
| bcc | string | No | BCC recipient(s) |
| replyTo | string | No | Reply-to address |
| templateId | string | No | ID of a saved template |
| templateData | object | No | Key-value pairs for template variables |
| addUnsubscribeFooter | boolean | No | Append unsubscribe link to email body |
| addListUnsubscribeHeader | boolean | No | Add List-Unsubscribe header |
* Either html, text, or templateId must be provided.
Send SMS
Deliver OTPs, alerts, and notifications globally via SMS with sender ID control.
DND Routes: For Nigerian numbers registered on the Do-Not-Disturb list, messages are automatically routed through DND-capable channels.
await senviok.sms.send({
from: 'Acme',
to: '+2348012345678',
text: 'Your verification code is 4829. Valid for 10 minutes.'
});Expected Response
{
"id": "msg_01HZ8a3b4c5d6e7f"
}Parameters
| Field | Type | Description |
|---|---|---|
| from | string | Sender ID (up to 11 alphanumeric characters) |
| to | string | Recipient phone number in E.164 format |
| text | string | Message content |
Send WhatsApp messages for order confirmations, shipping notifications, and alerts. Contact support to enable WhatsApp for your account.
await senviok.whatsapp.send({
from: '+14155238886',
to: '+2348012345678',
text: 'Your order #1234 has been shipped! Track at https://acme.com/track/1234'
});Expected Response
{
"id": "msg_01HZ8a3b4c5d6e7f"
}Templates
Create reusable email templates with {{variable}} placeholders. Pass data at send time to personalize each message.
// Create a template
const template = await senviok.templates.create({
name: 'Welcome Email',
subject: 'Welcome {{name}}!',
htmlContent: '<h1>Hello {{name}}</h1><p>Welcome to {{company}}.</p>'
});
// List all templates
const templates = await senviok.templates.list();
// Get a single template
const tmpl = await senviok.templates.get('tmpl_abc123');
// Update a template
await senviok.templates.update('tmpl_abc123', {
name: 'Updated Welcome',
subject: 'Hey {{name}}!',
htmlContent: '<h1>Hey {{name}}</h1><p>Great to have you.</p>'
});
// Delete a template
await senviok.templates.delete('tmpl_abc123');Expected Response
{
"id": "tmpl_abc123",
"name": "Welcome Email",
"subject": "Welcome {{name}}!",
"htmlContent": "<h1>Hello {{name}}</h1><p>Welcome to {{company}}.</p>",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}Using Templates When Sending
await senviok.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome {{name}}!',
templateId: template.id,
templateData: {
name: 'Sarah',
company: 'Acme Inc'
}
});Domains
Add custom sending domains and configure DKIM authentication to improve deliverability and send from your own addresses.
// Add a domain
const domain = await senviok.domains.create({ name: 'yourdomain.com' });
// List all domains
const domains = await senviok.domains.list();
// Get DKIM DNS records (add these to your DNS provider)
const dkim = await senviok.domains.getDkim('dom_abc123');
// Returns: { tokens: [...] } — add these as CNAME records
// Verify domain after adding DNS records
const result = await senviok.domains.verify('dom_abc123');
// Returns: { verified: true }Expected Response
{
"id": "dom_abc123",
"name": "yourdomain.com",
"status": "pending",
"createdAt": "2024-01-15T10:30:00Z"
}DNS Record Configuration Tips
- DKIM Records: Add the generated CNAME records to authenticate outgoing mail signatures for your domain.
- Domain Ownership Verification Record: The verification code provided for your domain is an independent
TXTrecord. - Important: Do not merge or append your domain verification code into your SPF (
v=spf1...) record. It must be added as its own standalone TXT record on your DNS host. Merging verification codes into SPF records invalidates SPF syntax and will hurt email deliverability.
Audiences
Organize your recipients into audiences (mailing lists). Each audience can contain multiple contacts.
// Create an audience
const audience = await senviok.audiences.create({
name: 'Newsletter Subscribers'
});
// List all audiences
const audiences = await senviok.audiences.list();
// Delete an audience
await senviok.audiences.delete('aud_abc123');Expected Response
{
"id": "aud_abc123",
"name": "Newsletter Subscribers",
"createdAt": "2024-01-15T10:30:00Z"
}Contacts
Add and manage contacts within an audience. Contacts are scoped to a specific audience.
// Add a contact to an audience
const contact = await senviok.contacts.create('aud_abc123', {
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe',
unsubscribed: false
});
// List contacts in an audience
const contacts = await senviok.contacts.list('aud_abc123');
// Remove a contact from an audience
await senviok.contacts.delete('aud_abc123', 'ct_xyz789');Expected Response
{
"id": "ct_xyz789",
"audienceId": "aud_abc123",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"unsubscribed": false,
"createdAt": "2024-01-15T10:30:00Z"
}Suppressions
Manage your suppression list to prevent sending to addresses that have bounced, complained, or unsubscribed. Senviok automatically adds hard bounces.
// Add an address to the suppression list
await senviok.suppressions.create({
email: 'bounced@example.com',
reason: 'hard_bounce'
});
// List all suppressed addresses
const suppressions = await senviok.suppressions.list();
// Remove from suppression list (re-enable sending)
await senviok.suppressions.delete('sup_abc123');Expected Response
{
"id": "sup_abc123",
"email": "bounced@example.com",
"reason": "hard_bounce",
"createdAt": "2024-01-15T10:30:00Z"
}Message Logs
Query your sending history with powerful filters. View delivery status, timestamps, and metadata for every message.
// Get recent messages
const logs = await senviok.messages.list({
take: 50,
sortOrder: 'desc'
});
// Filter by channel and status
const emailLogs = await senviok.messages.list({
channel: 'email',
status: 'sent',
take: 100
});
// Filter by date range and recipient
const filtered = await senviok.messages.list({
startDate: '2024-01-01',
endDate: '2024-01-31',
toAddress: 'user@example.com'
});
// Filter by sender and subject
const specific = await senviok.messages.list({
fromAddress: 'hello@yourdomain.com',
subject: 'Welcome',
skip: 0,
take: 20
});Expected Response
[
{
"id": "msg_abc123",
"channel": "email",
"status": "sent",
"toAddress": "user@example.com",
"fromAddress": "hello@yourdomain.com",
"subject": "Welcome",
"htmlBody": "<p>Hello</p>",
"textBody": "Hello",
"providerMessageId": "0107017a",
"createdAt": "2024-01-15T10:30:00Z"
}
]Webhooks
Receive real-time delivery notifications via HTTPS POST. Subscribe to events like message.sent, message.failed, message.delivered, and message.bounced.
Manage Webhooks
// Create a webhook
const webhook = await senviok.webhooks.create({
url: 'https://your-app.com/webhooks/senviok',
events: ['message.sent', 'message.failed', 'message.delivered', 'message.bounced']
});
console.log(webhook.secret); // Save this for signature verification
// List all webhooks
const webhooks = await senviok.webhooks.list();
// Get delivery logs for a webhook
const deliveries = await senviok.webhooks.logs('wh_abc123');
// Delete a webhook
await senviok.webhooks.delete('wh_abc123');Expected Response
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/senviok",
"secret": "whsec_2f5a0c1b9e3d4f",
"events": ["message.sent", "message.failed", "message.delivered", "message.bounced"],
"createdAt": "2024-01-15T10:30:00Z"
}Webhook Headers
| Header | Description |
|---|---|
| svk-signature | HMAC-SHA256 signature of the request body |
| svk-event-id | Unique ID for this webhook delivery |
| svk-timestamp | ISO 8601 timestamp of the event |
Example Payload
{
"event": "message.sent",
"messageId": "msg_01HZ8a3b4c5d",
"to": "user@example.com",
"channel": "email",
"timestamp": "2024-01-15T10:30:00Z",
"metadata": { "user_id": "usr_001" }
}Verify Signatures
Always verify the svk-signature header before processing to prevent spoofed requests.
// Built into the SDK — no extra code needed
const isValid = senviok.webhooks.verifySignature(
rawRequestBody, // The raw JSON string from the request
req.headers['svk-signature'],
webhook.secret // The secret from when you created the webhook
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}Error Handling
The SDK throws typed errors that you can catch and inspect. All errors include the HTTP status code, a human-readable message, and the full response body.
import { Senviok, ApiError } from 'senviok';
try {
await senviok.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Hello!',
html: '<p>Hi there</p>'
});
} catch (error) {
if (error instanceof ApiError) {
console.error('Status:', error.status); // 400, 401, 403, 429, 500
console.error('Message:', error.message); // Human-readable error
console.error('Body:', error.body); // Full error response
}
}Error Codes
| Status | Meaning | What To Do |
|---|---|---|
400 | Bad Request — Invalid or missing fields | Check your request parameters |
401 | Unauthorized — Missing or invalid API key | Verify your API key is correct |
403 | Forbidden — Insufficient permissions or suspended | Check your account status |
429 | Rate Limited — Too many requests | Retry with exponential backoff |
500 | Server Error — Something went wrong | Retry after a brief delay |
Rate Limits & Headers
All Senviok API requests are rate-limited to ensure system stability and fair resource usage. Standard accounts are allocated 100 requests per minute per API key.
You can monitor your current consumption in real time using the HTTP headers returned with every API response:
| Header | Description |
|---|---|
| X-RateLimit-Limit | The maximum number of requests allowed in the current 60-second window (default: 100). |
| X-RateLimit-Remaining | The number of requests remaining in the current window. |
| X-RateLimit-Reset | Unix timestamp (in seconds) when the current rate limit quota resets. |
Handling Rate Limits (HTTP 429)
If you exceed the rate limit, the API returns an HTTP 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait. Official Senviok SDKs handle rate limiting with automatic exponential backoff retries.
SMTP Relay
Prefer SMTP over the SDK? Configure frameworks like Laravel, Rails, WordPress, or any SMTP client to send through Senviok using your API key as the password.
Host / Server
mail.senviok.livePort
2525 (Recommended) or 587Username
apiPassword
[Your Senviok API Key]Encryption: STARTTLS is required. Most SMTP clients enable this by default. If you see connection errors, ensure TLS is enabled in your SMTP configuration.
