Send email from Ruby

Five steps: check your Ruby, create a test key, send to the sandbox, read the log, then verify a domain so you can send to anyone. Using Rails? The Rails quickstart puts the same steps in a service object.

1. Install

No SDK needed. The API is plain JSON over HTTPS, and net/http and json ship with Ruby.

shell
ruby --version   # 3.0 or newer; net/http and json ship with Ruby

2. Create an API key

Sign in, open API keys in the dashboard and create a test key. It starts with av_test_. Export it so the script can read it:

shell
export AVELTO_API_KEY=av_test_...

3. Send your first email

Every request carries the key as a bearer token. The small api helper below sends JSON, parses the response and aborts with the code and message from the error envelope on any non-2xx status.

Ruby
# send.rbrequire "net/http"require "json"API = "https://api.avelto.dev"HEADERS = {  "Authorization" => "Bearer #{ENV.fetch("AVELTO_API_KEY")}",  "Content-Type" => "application/json",}def api(method, path, body = nil)  uri = URI("#{API}#{path}")  req = Net::HTTP.const_get(method).new(uri, HEADERS)  req.body = JSON.generate(body) if body  res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }  data = res.body.to_s.empty? ? nil : JSON.parse(res.body)  unless res.is_a?(Net::HTTPSuccess)    abort "#{res.code} #{data["error"]["code"]}: #{data["error"]["message"]}"  end  dataendemail = api(:Post, "/v1/emails", {  from: "you@sandbox.avelto.dev",  to: "delivered@sandbox.avelto.dev",  subject: "Hello from Avelto",  text: "It works.",})puts email["id"] # "9c1f4a52-6f6e-4b8f-9b8e-2e1a5c7d3f10"
shell
ruby send.rb

The API answers 201 Created with the email id:

HTTP
HTTP/1.1 201 CreatedContent-Type: application/json{ "id": "9c1f4a52-6f6e-4b8f-9b8e-2e1a5c7d3f10" }

4. Check the log

Fetch the email by id with the same helper. status moves from queued to sent to delivered, and events records each step: email.queued, email.sent, email.delivered.

Ruby
email = api(:Get, "/v1/emails/#{email["id"]}")puts email["status"] # "queued", then "sent", then "delivered"email["events"].each { |e| puts "#{e["type"]} #{e["occurred_at"]}" }
JSON
{  "id": "9c1f4a52-6f6e-4b8f-9b8e-2e1a5c7d3f10",  "mode": "test",  "from": "you@sandbox.avelto.dev",  "to": ["delivered@sandbox.avelto.dev"],  "subject": "Hello from Avelto",  "status": "delivered",  "events": [    {      "id": "e1f0c3a4-8b2d-4c6e-9a1f-5d7b3e2c8a90",      "type": "email.queued",      "payload": {},      "occurred_at": "2026-09-17T10:12:04.000Z"    },    {      "id": "a7c2e9d1-3f4b-4a8e-b6c0-2d9e1f7b5c34",      "type": "email.sent",      "payload": { "test": true, "ses_message_id": "test-9c1f4a52-6f6e-4b8f-9b8e-2e1a5c7d3f10" },      "occurred_at": "2026-09-17T10:12:06.000Z"    },    {      "id": "c4b8d2f6-7e1a-4d3c-8f9b-6a2e0c5d1b78",      "type": "email.delivered",      "payload": { "test": true, "recipients": ["delivered@sandbox.avelto.dev"] },      "occurred_at": "2026-09-17T10:12:06.000Z"    }  ]}

5. Verify a domain

Add a domain, publish the DNS records it prints (an ownership TXT, an SPF TXT and a DMARC TXT, then three DKIM CNAMEs once the ownership record is found), then poll GET /v1/domains/:id until status is verified. The GET re-checks DNS on every call. Use a subdomain such as mail.acme.com.

Ruby
# verify_domain.rb (reuse the api helper from send.rb)def show(domain)  domain["dns_records"].each do |r|    puts "#{r["type"]}\t#{r["name"]}\t#{r["value"]}\t(#{r["purpose"]})"  endenddomain = api(:Post, "/v1/domains", { name: "mail.acme.com" })show(domain) # the ownership record first, with SPF and DMARC# Publish the records, then poll. GET re-checks DNS on every call.# Once the ownership record is found, the DKIM records appear: publish those too.while domain["status"] == "pending"  sleep 30  latest = api(:Get, "/v1/domains/#{domain["id"]}")  show(latest) if latest["ownership_verified"] && !domain["ownership_verified"]  domain = latestendputs domain["status"] # "verified" or "failed"
shell
ruby verify_domain.rb

Once the domain is verified, switch AVELTO_API_KEY to a live key (av_live_) and change from to an address on it, such as hello@mail.acme.com. Nothing else changes.

Next

  • Send email: every field, attachments, tags, scheduling and idempotency.
  • Webhooks: get events pushed to your app.
  • Test mode: test keys, the sandbox sender and the simulator addresses.