# `Swoosh.Adapters.AhaSend`
[🔗](https://github.com/swoosh/swoosh/blob/v1.28.0/lib/swoosh/adapters/aha_send.ex#L1)

An adapter that sends email using the AhaSend API.

For reference: [AhaSend API docs](https://ahasend.com/docs/api-reference)

**This adapter requires an API Client.** Swoosh comes with Hackney, Finch and Req out of the box.
See the [installation section](https://hexdocs.pm/swoosh/Swoosh.html#module-installation)
for details.

## Example

    # config/config.exs
    config :sample, Sample.Mailer,
      adapter: Swoosh.Adapters.AhaSend,
      api_key: "aha-sk-my-api-key",
      account_id: "my-account-id"

    # lib/sample/mailer.ex
    defmodule Sample.Mailer do
      use Swoosh.Mailer, otp_app: :sample
    end

## Recipients

AhaSend exposes two send endpoints and this adapter picks the one that
preserves the semantics of the email you built:

  * emails without `cc` or `bcc` are sent through `/messages`, which
    delivers an individual message to each recipient. Recipients do not
    see one another.

  * emails with `cc` or `bcc` are sent through `/messages/conversation`,
    which delivers a single message carrying the full `To`/`Cc`/`Bcc`
    headers, the way a regular mail client would.

## Delivering many emails

`deliver_many/2` sends each email in its own request, so a problem with one
email (an invalid recipient, say) never affects the others. Results are
returned in the same order as the emails passed in. Delivery stops at the
first failure and returns that error; emails already sent are not rolled
back.

## Using with provider options

    import Swoosh.Email

    new()
    |> from("nora@example.com")
    |> to("shushu@example.com")
    |> subject("Hello, Wally!")
    |> text_body("Hello")
    |> put_provider_option(:tags, ["welcome", "onboarding"])
    |> put_provider_option(:tracking, %{open: true, click: false})
    |> put_provider_option(:idempotency_key, "unique-key-123")

## Provider Options

  * `tags` (list of strings) - `tags`, categorize the message

  * `substitutions` (map) - `substitutions`, template variables applied to
    the subject and body

  * `tracking` (map) - `tracking`, override the account open/click tracking
    defaults, for example `%{open: true, click: false}`

  * `retention` (map) - `retention`, override the account data retention
    defaults, for example `%{metadata: 30, data: 7}`

  * `schedule` (map) - `schedule`, defer delivery, for example
    `%{first_attempt: "2026-01-01T00:00:00Z"}`

  * `sandbox` (boolean) - `sandbox`, accept and validate the message
    without delivering it

  * `sandbox_result` (string) - `sandbox_result`, the outcome to simulate in
    sandbox mode. One of `deliver`, `bounce`, `defer`, `fail`, `suppress`

  * `idempotency_key` (string) - sent as the `Idempotency-Key` header so a
    retried request cannot deliver the message twice

# `deliver`

# `deliver_many`

# `validate_config`

# `validate_dependency`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
