Packages
A compact Req-backed Elixir client for the Nuntly REST API, generated from OpenAPI.
Current section
Files
Jump to
Current section
Files
README.md
# Nuntly
[](https://github.com/mindreframer/nuntly/actions/workflows/ci.yml)
[](https://hex.pm/packages/nuntly)
[](https://hexdocs.pm/nuntly)
**A compact Req-backed Elixir client for the [Nuntly REST API](https://nuntly.com/docs)**
Nuntly is generated from the API's OpenAPI document and supports both
configured, Repo-style modules and explicit clients.
## Configured module API
For the common case where an application has one stable configuration, define
a Repo-style module:
```elixir
defmodule MyApp.Nuntly do
use Nuntly, otp_app: :my_app
end
```
Configure it using the module as the application environment key:
```elixir
# config/runtime.exs
config :my_app, MyApp.Nuntly,
api_key: System.fetch_env!("NUNTLY_API_KEY")
```
All operations are then available directly, without a client argument:
```elixir
{:ok, response} =
MyApp.Nuntly.send_email(%{
from: "hello@example.com",
to: "person@example.net",
subject: "Hello",
text: "Sent from Elixir"
})
MyApp.Nuntly.list_messages(%{"domainId" => domain_id, limit: 25})
```
`client/0` is overridable when an application needs custom credential lookup or
test behavior.
## Explicit client API
Use the resource modules directly when configuration varies by request or
tenant:
```elixir
client = Nuntly.new(api_key: tenant.api_key)
Nuntly.Emails.send_email(client, payload,
headers: [{"idempotency-key", idempotency_key}]
)
```
`Nuntly.new/1` also reads `NUNTLY_API_KEY` when `:api_key` is omitted. Other
client options are passed to `Req.new/1`:
```elixir
client = Nuntly.new(receive_timeout: 10_000, retry: :transient)
```
Both APIs follow the same conventions:
- Path values are positional arguments and are URL-escaped.
- JSON payloads are plain maps passed as `body`.
- Query strings are plain maps passed as `params`.
- The final keyword list is passed to Req, allowing headers and other
per-request options.
The explicit resource API additionally takes the client as its first argument.
Map keys are forwarded unchanged. For camel-cased API fields, use their exact
OpenAPI spelling, usually as strings.
Req returns `{:ok, %Req.Response{}}` for HTTP responses, including non-2xx
statuses, and `{:error, exception}` for transport failures.
See the generated [API reference](https://github.com/mindreframer/nuntly/blob/main/docs/rest-api-reference.md) for every function,
argument, request field, HTTP path, and examples for both calling styles.
The generated API modules are:
- `Nuntly.Agents`
- `Nuntly.ApiKeys`
- `Nuntly.Domains`
- `Nuntly.Emails`
- `Nuntly.Inboxes`
- `Nuntly.Messages`
- `Nuntly.Namespaces`
- `Nuntly.Organizations`
- `Nuntly.Threads`
- `Nuntly.Webhooks`
- `Nuntly.WebhooksEvents`
## Regenerating
The Bun generator lives in the [`generator/`](https://github.com/mindreframer/nuntly/tree/main/generator)
directory:
```bash
cd generator
bun install
bun test
bun run generate
cd ..
mix test
```
See [`generator/README.md`](https://github.com/mindreframer/nuntly/blob/main/generator/README.md)
for its design, options, and coverage commands. Generated Elixir source is kept in
`lib/nuntly/generated/`, and the generated Markdown reference is written to
`docs/rest-api-reference.md`. Custom code should live outside generated files.
## Installation
Add `nuntly` to your dependencies:
```elixir
def deps do
[
{:nuntly, "~> 0.1.0"}
]
end
```