Get Started
Elixir
Send emails with the Unsent Elixir SDK
The Unsent Elixir SDK provides a simple and intuitive way to send transactional emails, manage contacts, campaigns, and domains from your Elixir applications.
Installation
Add unsent to your list of dependencies in mix.exs:
def deps do
[
{:unsent, "~> 1.0.2"}
]
endThen run mix deps.get to install the package.
Quick Start
# Initialize the client
client = Unsent.new("un_your_api_key")
# Send an email
{:ok, email} = Unsent.Emails.send(client, %{
to: "user@example.com",
from: "hello@yourdomain.com",
subject: "Welcome!",
html: "<p>Welcome to our service!</p>"
})Client Initialization
With API Key
client = Unsent.new("un_xxx")Using Environment Variable
Set UNSENT_API_KEY environment variable and initialize without passing the key:
client = Unsent.new()With Custom Options
client = Unsent.new("un_xxx",
base_url: "https://api.unsent.dev/v1",
raise_on_error: false # Return tuples instead of raising
)Sending Emails
Basic Email
{:ok, email} = Unsent.Emails.send(client, %{
to: "recipient@example.com",
from: "sender@yourdomain.com",
subject: "Hello from Elixir",
html: "<h1>Hello</h1><p>Email from Elixir SDK</p>",
text: "Hello! Email from Elixir SDK"
})Email with Attachments
Unsent.Emails.send(client, %{
to: "user@example.com",
from: "hello@company.com",
subject: "Document Attached",
html: "<p>Please find the document attached</p>",
attachments: [
%{
filename: "invoice.pdf",
content: "base64-encoded-content-here"
}
]
})Scheduled Email
# Schedule for 1 hour from now
scheduled_time = DateTime.utc_now() |> DateTime.add(3600, :second)
Unsent.Emails.send(client, %{
to: "user@example.com",
from: "hello@company.com",
subject: "Scheduled Email",
html: "<p>This email was scheduled</p>",
scheduledAt: DateTime.to_iso8601(scheduled_time)
})Batch Emails
Send up to 100 emails in a single API call:
emails = [
%{
to: "user1@example.com",
from: "hello@company.com",
subject: "Welcome User 1",
html: "<p>Welcome!</p>"
},
%{
to: "user2@example.com",
from: "hello@company.com",
subject: "Welcome User 2",
html: "<p>Welcome!</p>"
}
]
{:ok, result} = Unsent.Emails.batch(client, emails)Idempotent Requests
Use idempotency keys to safely retry requests:
Unsent.Emails.send(client, payload,
headers: [{"Idempotency-Key", "unique-request-id-123"}]
)Managing Emails
List Emails
# List all emails
{:ok, emails} = Unsent.Emails.list(client)
# With filters and pagination
Unsent.Emails.list(client,
page: 1,
limit: 50,
startDate: "2024-01-01T00:00:00Z",
endDate: "2024-12-31T23:59:59Z",
domainId: "domain_id"
)
# Filter by multiple domains
Unsent.Emails.list(client, domainId: ["domain_1", "domain_2"])Get Email
{:ok, email} = Unsent.Emails.get(client, "email_id")Update Email
Unsent.Emails.update(client, "email_id", %{
scheduledAt: "2024-12-01T10:00:00Z"
})Cancel Email
Unsent.Emails.cancel(client, "email_id")Email Events
# Get bounced emails
{:ok, bounces} = Unsent.Emails.get_bounces(client, page: 1, limit: 20)
# Get spam complaints
{:ok, complaints} = Unsent.Emails.get_complaints(client)
# Get unsubscribes
{:ok, unsubscribes} = Unsent.Emails.get_unsubscribes(client)Contact Books & Contacts
Contact Books
# List contact books
{:ok, books} = Unsent.ContactBooks.list(client)
# Create contact book
{:ok, book} = Unsent.ContactBooks.create(client, %{
name: "Newsletter Subscribers"
})
# Get contact book
{:ok, book} = Unsent.ContactBooks.get(client, book_id)
# Update contact book
Unsent.ContactBooks.update(client, book_id, %{name: "Updated Name"})
# Delete contact book
Unsent.ContactBooks.delete(client, book_id)Contacts
# List contacts
{:ok, contacts} = Unsent.Contacts.list(client, book_id)
# With filters
Unsent.Contacts.list(client, book_id,
page: 1,
limit: 50,
emails: "user1@example.com,user2@example.com"
)
# Create contact
{:ok, contact} = Unsent.Contacts.create(client, book_id, %{
email: "user@example.com",
firstName: "John",
lastName: "Doe",
data: %{plan: "premium", signupDate: "2024-01-01"}
})
# Get contact
{:ok, contact} = Unsent.Contacts.get(client, book_id, contact_id)
# Update contact
Unsent.Contacts.update(client, book_id, contact_id, %{
firstName: "Jane"
})
# Upsert contact (create or update)
Unsent.Contacts.upsert(client, book_id, contact_id, %{
email: "user@example.com",
firstName: "John"
})
# Delete contact
Unsent.Contacts.delete(client, book_id, contact_id)Campaigns
# List campaigns
{:ok, campaigns} = Unsent.Campaigns.list(client)
# Create campaign
{:ok, campaign} = Unsent.Campaigns.create(client, %{
name: "Welcome Series",
subject: "Welcome {{firstName}}!",
html: "<h1>Hi {{firstName}}</h1><p>Welcome to {{company}}</p>",
from: "hello@company.com",
contactBookId: book_id
})
# Get campaign
{:ok, campaign} = Unsent.Campaigns.get(client, campaign_id)
# Schedule campaign
Unsent.Campaigns.schedule(client, campaign_id, %{
scheduledAt: "2024-12-01T10:00:00Z"
})
# Pause campaign
Unsent.Campaigns.pause(client, campaign_id)
# Resume campaign
Unsent.Campaigns.resume(client, campaign_id)Domains
# List domains
{:ok, domains} = Unsent.Domains.list(client)
# Create domain
{:ok, domain} = Unsent.Domains.create(client, %{
name: "yourdomain.com",
region: "us-east-1"
})
# Verify domain
Unsent.Domains.verify(client, domain_id)
# Get domain
{:ok, domain} = Unsent.Domains.get(client, domain_id)
# Delete domain
Unsent.Domains.delete(client, domain_id)Templates
# List templates
{:ok, templates} = Unsent.Templates.list(client)
# Create template
{:ok, template} = Unsent.Templates.create(client, %{
name: "Welcome Email",
subject: "Welcome {{name}}!",
html: "<h1>Hi {{name}}</h1><p>Welcome to {{company}}</p>"
})
# Get template
{:ok, template} = Unsent.Templates.get(client, template_id)
# Update template
Unsent.Templates.update(client, template_id, %{
subject: "Updated: Welcome {{name}}!"
})
# Delete template
Unsent.Templates.delete(client, template_id)
# Use template in email
Unsent.Emails.send(client, %{
to: "user@example.com",
from: "hello@company.com",
templateId: template_id,
templateData: %{name: "John", company: "Acme Inc"}
})Suppressions
Manage your suppression list to prevent emails from being sent to certain addresses:
# List all suppressions
{:ok, suppressions} = Unsent.Suppressions.list(client)
# With filters
Unsent.Suppressions.list(client,
page: 1,
limit: 50,
search: "example.com",
reason: "HARD_BOUNCE" # or "COMPLAINT", "MANUAL", "UNSUBSCRIBE"
)
# Add to suppression list
Unsent.Suppressions.add(client, %{
email: "blocked@example.com",
reason: "MANUAL"
})
# Remove from suppression list
Unsent.Suppressions.delete(client, "blocked@example.com")Analytics
Track your email performance and sender reputation:
# Get overall analytics
{:ok, analytics} = Unsent.Analytics.get(client)
# Get time series data
Unsent.Analytics.get_time_series(client, days: 30)
Unsent.Analytics.get_time_series(client, days: 7, domain: "yourdomain.com")
# Get reputation score
Unsent.Analytics.get_reputation(client)
Unsent.Analytics.get_reputation(client, domain: "yourdomain.com")Settings
# Get team settings
{:ok, settings} = Unsent.Settings.get(client)API Keys
# List API keys
{:ok, keys} = Unsent.ApiKeys.list(client)
# Create API key
{:ok, key} = Unsent.ApiKeys.create(client, %{
name: "Production Key",
permission: "FULL" # or "SENDING"
})
# Delete API key
Unsent.ApiKeys.delete(client, key_id)Error Handling
Exceptions (Default)
By default, the SDK raises exceptions on errors:
try do
Unsent.Emails.send(client, invalid_payload)
rescue
e in Unsent.HTTPError ->
IO.puts("Error: #{e.error["message"]}")
IO.puts("Status code: #{e.status_code}")
endResult Tuples
Return {:ok, data} or {:error, reason} tuples instead:
client = Unsent.new("un_xxx", raise_on_error: false)
case Unsent.Emails.send(client, payload) do
{:ok, email} ->
IO.puts("Email sent successfully!")
{:error, error} ->
IO.puts("Failed to send: #{error["message"]}")
endAdvanced Features
Custom Headers
Unsent.Emails.send(client, payload,
headers: [
{"Idempotency-Key", "unique-id"},
{"X-Custom-Header", "value"}
]
)Base URL Override
client = Unsent.new("un_xxx", base_url: "https://custom-api.unsent.dev/v1")