# MillionSend v0.4.0 - Table of Contents

> Official Elixir SDK for MillionSend — a self-hostable, Resend-compatible email API.

## Modules

- [MillionSend](MillionSend.md): Official Elixir client for [MillionSend](https://github.com/MillionSend/millionsend) —
a self-hostable, Resend-compatible email API.
- [MillionSend.ApiKeys](MillionSend.ApiKeys.md): 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).
- [MillionSend.ApiKeys.ApiKey](MillionSend.ApiKeys.ApiKey.md): An API key. `token` is returned only by `create/2` — store it, it cannot be
fetched again. `remove/2` populates `id` plus `deleted`.

- [MillionSend.BatchError](MillionSend.BatchError.md): One rejected item of a permissive batch (`batch_validation: :permissive`):
its position in the request array and the validation message.

- [MillionSend.Broadcasts](MillionSend.Broadcasts.md): Broadcasts. Create a draft, then `send/3` it (optionally scheduled), or pass
`send: true` (plus an optional `scheduled_at`) to `create/2` to do both at
once. Target with an optional `segment_id` and/or `topic_id`; neither means
every contact of the team.
- [MillionSend.Broadcasts.Broadcast](MillionSend.Broadcasts.Broadcast.md): A broadcast — an email sent to the team's contacts, optionally targeted.
- [MillionSend.Client](MillionSend.Client.md): A resolved MillionSend client: API key, base URL, User-Agent and the HTTP
module to run requests through. Build one with `MillionSend.client/1`.

- [MillionSend.ContactProperties](MillionSend.ContactProperties.md): Contact property definitions. Input maps are sent as given: `create/2`
accepts `key`, `type` (`:string | :number`) and `fallback_value`; `update/3`
accepts `fallback_value` (`nil` clears it).
- [MillionSend.ContactProperties.ContactProperty](MillionSend.ContactProperties.ContactProperty.md): 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`.

- [MillionSend.Contacts](MillionSend.Contacts.md): Contacts are team-global (one per email per team, case-insensitive) and
addressable by id **or** email — email wins when both are given.
- [MillionSend.Contacts.BatchResponse](MillionSend.Contacts.BatchResponse.md): 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`.

- [MillionSend.Contacts.BatchResponse.Item](MillionSend.Contacts.BatchResponse.Item.md): An accepted batch item: its request `index`, the contact `id` and `status` (`"created" | "updated" | "skipped"`).
- [MillionSend.Contacts.Contact](MillionSend.Contacts.Contact.md): A contact. `remove/2` populates `contact` (its id) plus `deleted`.
`properties` is a map of `key => %{"type" => "string" | "number", "value" => ...}`.

- [MillionSend.Deliverability](MillionSend.Deliverability.md): Account-level deliverability score over the trailing window.
- [MillionSend.Domains](MillionSend.Domains.md): Sending domains: add one, publish the returned DNS `records`, then `verify/2`.
- [MillionSend.Domains.Domain](MillionSend.Domains.Domain.md): 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.

- [MillionSend.Domains.Domain.Record](MillionSend.Domains.Domain.Record.md): 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`.

- [MillionSend.Emails](MillionSend.Emails.md): Send, list, fetch, reschedule and cancel emails.
- [MillionSend.Emails.BatchResponse](MillionSend.Emails.BatchResponse.md): 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.

- [MillionSend.Emails.Email](MillionSend.Emails.Email.md): An email. `send/2`, `update/3`, `cancel/2` and `remove/2` populate only `id`/`object` (plus `deleted`).
- [MillionSend.Emails.Insights](MillionSend.Emails.Insights.md): 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).

- [MillionSend.Emails.Insights.Check](MillionSend.Emails.Insights.Check.md): 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`.

- [MillionSend.HTTP](MillionSend.HTTP.md): 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.

- [MillionSend.HTTP.Req](MillionSend.HTTP.Req.md): Default `MillionSend.HTTP` implementation, backed by Req.
- [MillionSend.List](MillionSend.List.md): 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.

- [MillionSend.Segments](MillionSend.Segments.md): 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`.
- [MillionSend.Segments.Segment](MillionSend.Segments.Segment.md): A dynamic segment — a saved filter over the team's contacts.
- [MillionSend.Suppressions](MillionSend.Suppressions.md): 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.
- [MillionSend.Suppressions.Suppression](MillionSend.Suppressions.Suppression.md): 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`.

- [MillionSend.Templates](MillionSend.Templates.md): Templates. Every member function takes the template id **or** its alias.
- [MillionSend.Templates.Template](MillionSend.Templates.Template.md): 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`.

- [MillionSend.Topics](MillionSend.Topics.md): Subscription topics. Input maps are sent as given: `name`,
`default_subscription` (`:opt_in | :opt_out`), `description` and `visibility`
(`:private | :public`).
- [MillionSend.Topics.Topic](MillionSend.Topics.Topic.md): A subscription topic — a granular unsubscribe category.
- [MillionSend.Usage](MillionSend.Usage.md): Plan limits and today's send count — a MillionSend extension with no Resend
equivalent.
- [MillionSend.Webhooks](MillionSend.Webhooks.md): Webhooks. Input maps are sent as given: `create/2` accepts `endpoint`,
`events` and an optional `signing_secret` (carry over an existing `whsec_`
secret so the receiver keeps verifying unchanged); `update/3` accepts
`endpoint`, `events` and `status`.
- [MillionSend.Webhooks.Webhook](MillionSend.Webhooks.Webhook.md): A webhook endpoint. `signing_secret` is returned by `create/2` and `get/2`;
`status` is `"enabled" | "disabled"`. `remove/2` populates `id` plus `deleted`.

- Exceptions
  - [MillionSend.Error](MillionSend.Error.md): The error every non-2xx response carries, plus the client-side/transport case.

