SendClipper Rust SDK
The official Rust library for the SendClipper email API.
Async, on tokio and reqwest. TLS through rustls by default (default-features = false, features = ["native-tls"] for the platform's own). Rust 1.85 or newer. API reference on docs.rs.
Setup
Create an API key in the dashboard under API keys.
let client = new;
// or: sendclipper::Client::from_env() reads SENDCLIPPER_API_KEY
A Client is cheap to clone and safe to share across tasks.
Send an email
use ;
async
from must be a bare address on a domain you verified in SendClipper. Each message has one recipient in to; for several, use batch().send().
Send with a template
Design and publish a template in the dashboard, then send it by id or by its send name:
let mut variables = new;
variables.insert;
client
.emails
.send
.await?;
A tag with no value and no {{tag|fallback}} is refused by name (template_variables_missing), never sent blank.
Send a batch
Up to 500 messages in one request. Each item is accepted or refused on its own:
let res = client.batch.send.await?;
for item in &res.data
Errors
Every method returns Result<T, sendclipper::Error>. A refusal from the API, or a request that never got an answer, is an Error:
match client.emails.send.await
Retries and idempotency
Network errors, 429 and 5xx answers are retried twice with backoff, honouring Retry-After. Every JSON write carries an Idempotency-Key, and the API answers a repeated key with the first result for 24 hours. A retried send therefore never goes out twice.
To make your own retries safe as well (a job that runs again after a crash), pass a key that names the logical operation:
client.with_idempotency_key.emails.send.await?;
Options
Per call, on a cheap copy of the client:
| Method | Meaning |
|---|---|
with_idempotency_key(key) |
Your own key for a write |
with_timeout(duration) |
Per-attempt timeout (default 30 s) |
with_max_retries(n) |
Retries (default 2) |
with_header(name, value) |
An extra request header |
Client: Client::builder().api_key(..).base_url(..).timeout(..).max_retries(..).default_header(..).http_client(reqwest_client).build(). The base URL also reads SENDCLIPPER_BASE_URL.
Stream every page
Lists that span pages have a list_all method that returns a Stream:
use TryStreamExt;
let bounced = client.emails.list_all;
pin_mut!;
while let Some = bounced.try_next.await?
Verify webhooks
SendClipper signs each delivery. Verify it against the raw body, before parsing. With axum:
use ;
async
The headers can be an http::HeaderMap (axum, actix-web, hyper), name/value pairs, or the header's value itself. During a secret rotation a delivery carries two signatures and either one is accepted. A delivery signed more than five minutes away from now is refused. client.webhooks().verify(...) is the same check.
To test your handler locally, sendclipper::webhook_signature_header(secret, body, None) builds a valid header.
Sandboxes
A sandbox traps mail while you develop: nothing is delivered.
use Duration;
let sandbox = client.sandboxes.create.await?;
let creds = client.sandboxes.credentials.await?; // SMTP host, port, username, password
// Or send through the sandbox's JSON door with its own token, using the same fields as emails().send():
let token = client.sandboxes.reset_credentials.await?;
client.sandboxes.send.await?;
// In a test: wait for the message to arrive
let msg = client
.sandboxes
.messages
.wait_for
.await?;
Everything else
| Resource | Methods |
|---|---|
emails() |
send, get, list, list_all, stats |
batch() |
send |
domains() |
list, create, records, verify, enable_receiving, disable_receiving, set_region, deletion_preview, remove |
templates() |
list, get, html, create, update, remove, duplicate, publish, unpublish, preview, set_tags, projects |
templates().tags() |
list, create, update, remove |
templates().assets() |
list, upload |
sandboxes() |
list, get, create, update, remove, credentials, reset_credentials, send |
sandboxes().messages() |
list, get, raw, remove, clear, mark_all_read, wait_for, wait_for_next |
webhooks() |
list, create, update, remove, rotate_secret, deliveries, verify |
webhooks().dispatches() |
list, list_all, get, replay, replay_all |
contacts() |
list, list_all, create, import, import_preview, export |
audiences() |
list |
suppressions() |
list, list_all, create, remove, export |
mailboxes() |
list, get, create, update, archive |
mailboxes().messages() |
list, list_all, get, attachment |
automations() |
enroll |
workspace() |
get |
api_keys() |
list |
Management routes need a key with Full access. A sending-only key can call emails().send and batch().send.
Full API reference: https://sendclipper.com/docs.
License
MIT