Modules
Official Elixir client for MillionSend — a self-hostable, Resend-compatible email API.
API keys. Input maps are sent as given: name, permission
(:full_access, the default, or :sending_access) and domain_id
(restrict a sending key to one domain).
An API key. token is returned only by create/2 — store it, it cannot be
fetched again. remove/2 populates id plus deleted.
One rejected item of a permissive batch (batch_validation: :permissive):
its position in the request array and the validation message.
A broadcast — an email sent to the team's contacts, optionally targeted.
A resolved MillionSend client: API key, base URL, User-Agent and the HTTP
module to run requests through. Build one with MillionSend.client/1.
A custom contact property definition: key, type ("string" | "number")
and the fallback_value used when a contact has no value. remove/2
populates id plus deleted.
Contacts are team-global (one per email per team, case-insensitive) and addressable by id or email — email wins when both are given.
The result of MillionSend.Contacts.create_batch/3: one Item per
successful request item (in request order), per-status counts
(created/updated/skipped/failed, summing to the request length) and,
in permissive mode, the failed items as errors.
An accepted batch item: its request index, the contact id and status ("created" | "updated" | "skipped").
A contact. remove/2 populates contact (its id) plus deleted.
properties is a map of key => %{"type" => "string" | "number", "value" => ...}.
A contact's effective subscription to one topic, as returned by
MillionSend.Contacts.list_topics/2. subscription is "opt_in" or
"opt_out"; explicit is false when that is the topic's default rather
than the contact's own choice.
Account-level deliverability score over the trailing window.
Sending domains: add one, publish the returned DNS records, then verify/2.
A sending domain. records lists the DNS records to publish (empty on list
and delete responses); capabilities is the %{"sending" => ..., "receiving" => ...} map as returned by the API.
One DNS record to publish for a domain: record (the role, e.g. SPF, DKIM,
DMARC or Tracking), name, type, ttl, value, status and, for MX,
priority.
Send, list, fetch, reschedule and cancel emails.
The result of a permissive MillionSend.Emails.send_batch/3: data holds
the accepted emails (id only) and errors the rejected items by request index.
An email. send/2, update/3, cancel/2 and remove/2 populate only id/object (plus deleted).
The pre-send best-practice report computed when an email was sent. score
is 0–10 (one decimal); band is a plain string
("excellent" | "good" | "needs_attention" | "at_risk", open to future values).
One best-practice check from an insights report. id is an open set (the
catalog grows across score versions), and severity/status are plain
strings so future wire values never break decoding. detail is free-form
JSON (a map) or nil.
The error every non-2xx response carries, plus the client-side/transport case.
Behaviour for the swappable HTTP layer. The default is MillionSend.HTTP.Req;
tests inject a stub by building a client with http_client: set to a module
implementing this behaviour.
Default MillionSend.HTTP implementation, backed by Req.
The pagination envelope returned by list endpoints: data holds the cast
structs, has_more says whether another page exists. Paginate with the
after:/before: keyset cursors.
Segments — a saved filter over the team's contacts (dynamic, a MillionSend
extension over Resend's static segments); a segment without a filter is a
plain list contacts are added to explicitly. get/2 returns a live
contact_count.
A dynamic segment — a saved filter over the team's contacts.
The suppression list — addresses that are never sent to. Entries come from bounces, complaints and unsubscribes, or are added here. Addressable by id or email.
A suppressed address. origin is "bounce" | "complaint" | "manual" | "unsubscribe"; source_id is the email whose bounce/complaint created the
entry (nil otherwise). Batch and remove/2 responses populate id plus
deleted.
Templates. Every member function takes the template id or its alias.
A stored email template. Write responses populate only id/object;
get/2 returns the full record. alias is a case-sensitive handle that
resolves in place of the id. remove/2 populates id plus deleted.
Subscription topics. Input maps are sent as given: name,
default_subscription (:opt_in | :opt_out), description and visibility
(:private | :public).
A subscription topic — a granular unsubscribe category.
Plan limits and today's send count — a MillionSend extension with no Resend equivalent.
A webhook endpoint. signing_secret is returned by create/2 and get/2;
status is "enabled" | "disabled". remove/2 populates id plus deleted.