unitpost
Official Unitpost SDK for Ruby. Send email and manage contacts, segments, campaigns, templates, domains, suppressions, and webhooks.
Install
gem install unitpost
Or add to your Gemfile:
gem "unitpost"
Requires Ruby 3.0+.
Quick start
require "unitpost"
unitpost = Unitpost::Client.new # reads UNITPOST_API_KEY (or pass api_key:)
result = unitpost.emails.send({
from: "Acme <you@yourdomain.com>", # bare address works too
to: "customer@example.com",
subject: "Hello",
html: "<p>It works!</p>"
})
if result.error
warn "#{result.error.code}: #{result.error.}"
else
puts result.data["id"]
end
Every method returns a Unitpost::Result with #data and #error (and a
#success? helper). An API-level failure populates #error (a
Unitpost::Error) instead of raising.
Authentication
Pass api_key: to Unitpost::Client.new, or set UNITPOST_API_KEY. Create a
key at unitpost.com → Settings → API keys.
Client surface
| Accessor | Covers |
|---|---|
emails |
Send, batch, list, get, update, stats, inbound (received_*) |
contacts |
CRUD, import jobs |
contact_fields |
Custom field definitions |
segments |
Segments + membership |
topics |
Topics + contact topic prefs |
campaigns |
Draft, schedule, send, pause/resume |
templates |
Template CRUD |
brand_kits |
Brand kit |
domains |
Domains + verify |
webhooks |
Endpoints + verify |
api_keys |
API key management |
suppressions |
Suppression list |
usage |
Billing-period usage snapshot |
Pagination
unitpost.contacts.list_all.each do |contact|
puts contact["email"]
end
Suppressions
The suppression list holds addresses excluded from every send — single, batch, and campaign, including cc/bcc — case-insensitively. Hard bounces and spam complaints are added automatically; you can also add your own:
# Suppress one address, or many in a single call (idempotent — re-adding is a no-op).
unitpost.suppressions.create({ email: "bounced@example.com", reason: "manual" })
unitpost.suppressions.create({ emails: ["a@example.com", "b@example.com"] })
# Look one up by id or email; list (optionally filter scope); un-suppress.
unitpost.suppressions.get("bounced@example.com")
unitpost.suppressions.list_all.each { |s| puts "#{s["email"]} #{s["reason"]}" }
unitpost.suppressions.delete("bounced@example.com")
reason accepts manual, import, or api — the engine-written bounce and
complaint reasons are read-only. Unitpost-wide (platform) entries are visible
but can't be removed via the API.
Verifying webhooks
event = Unitpost.verify_webhook(
payload: raw_body, # the raw request body string
secret: ENV.fetch("UNITPOST_WEBHOOK_SECRET"),
headers: request.headers
)
Or from the client (Resend-style alias):
event = client.webhooks.verify(payload: raw_body, secret: secret, headers: request.headers)
Idempotency
emails.send and emails.batch are safe to retry by default — when you don't
pass idempotency_key:, the SDK generates one so an automatic retry can't
double-send. Pass your own to dedupe across separate calls:
unitpost.emails.send({ ... }, idempotency_key: SecureRandom.uuid)
unitpost.emails.batch([ ... ], idempotency_key: SecureRandom.uuid)
The server dedupes on
(workspace, idempotency key)for 24h and replays the original result instead of re-sending (the email id for a send, the full list envelope for a batch).
Retries
Transient failures are retried automatically: 429, 5xx, and transport errors
(timeouts / network) retry up to max_retries times (default 2). A 429/503
Retry-After is honored; otherwise exponential backoff with full jitter is used.
Client errors (401/403/404/409/422) are never retried. Only requests
safe to replay are retried: GETs and writes carrying an idempotency key (which
emails.send and emails.batch always do); any other keyless write is never
auto-retried.
# Defaults shown; set max_retries: 0 to disable.
unitpost = Unitpost::Client.new(max_retries: 2, retry_base_delay: 0.5, max_retry_delay: 20.0)
Resources
| | |
| --- | --- |
| Docs + API reference | https://www.unitpost.com/docs |
| Product / SMTP / MCP guides | https://www.unitpost.com/guides |
| OpenAPI JSON | https://www.unitpost.com/api/v1/openapi.json |
| LLM index | https://www.unitpost.com/llms.txt |
| Dashboard / API keys | https://www.unitpost.com |
| Email components (@unitpost/email) | https://www.unitpost.com/components |
| Template gallery | https://www.unitpost.com/templates/gallery |
| Playground | https://www.unitpost.com/playground |
| Migration Assistant | https://www.unitpost.com/migration |
| MCP + Agent Skills | https://www.unitpost.com/guides#ai-mcp · https://www.unitpost.com/guides#ai-skills |
| Support | support@unitpost.com |
License
MIT