apiddress

Official Ruby SDK for the APIddress email validation API.

  • Zero runtime gem dependencies (stdlib net/http only)
  • Ruby 3.0+, immutable Data value objects, fully type-documented
  • Automatic retry with backoff on 429 and 5xx (batch creation is never retried)

Install

gem install apiddress

Or add to your Gemfile:

gem "apiddress"

Quickstart

require "apiddress"

client = Apiddress::Client.new(ENV["APIDDRESS_API_KEY"])

result = client.validate_email("ada@stripe.com")
puts result.status # => "valid"
puts result.score  # => 0.98

Configuration

client = Apiddress::Client.new(
  "YOUR_API_KEY",
  base_url:    "https://api.apiddress.com", # default
  timeout:     10,                          # per-request timeout (seconds), default 10
  max_retries: 2,                           # retries on 429/5xx, default 2
)

Usage

Validate one email

result = client.validate_email(
  "john@company.com",
  check_smtp:       false, # default
  allow_role_based: true,  # server default
)
# result.status: "valid" | "invalid" | "risky" | "disposable" | "unknown"
# result.suggestion: "john@gmail.com" for typo-like addresses, else nil
# result.checks: Apiddress::ValidationChecks (syntax, domain_exists, mx, smtp, ...)

A malformed value (e.g. "not-an-email") is a verdict, not an error: you get status == "invalid" with reason == "invalid_syntax".

Validate up to 100 emails synchronously

response = client.validate_emails(["a@example.com", "b@example.com"])
puts response.count
response.results.each { |r| puts "#{r.email} #{r.status}" }

Batch jobs (up to 5000 emails)

batch = client.create_batch(
  emails,
  callback_url: "https://yourapp.com/webhooks/apiddress", # optional
)

done = client.wait_for_batch(
  batch.batch_id,
  poll_interval: 1.0,  # default
  timeout:       60.0, # default
)
puts "#{done.status} #{done.results.length}"

# Or poll yourself:
status = client.get_batch(batch.batch_id)

wait_for_batch returns the terminal state ("completed" or "failed") — check status before using results.

Account

profile = client.me                  # plan, limits, usage
usage   = client.usage               # current month
may     = client.usage("2026-05")    # specific month
health  = client.health              # no auth required

Error handling

Every failed request raises an Apiddress::Error:

require "apiddress"

begin
  client.validate_email("john@company.com")
rescue Apiddress::Error => err
  puts err.status  # 429
  puts err.code    # "quota_exceeded"
  puts err.message # "Monthly request limit exceeded."
  p err.details    # {"requests_used"=>..., "requests_limit"=>...}
end
status code
400 invalid_request
401 unauthorized
404 not_found
429 quota_exceeded
500 internal_error
0 timeout (request or wait_for_batch timeout)

Development

bundle install

# Unit tests (no network required):
ruby test/test_client.rb

# Integration tests need a live backend:
APIDDRESS_BASE_URL=http://localhost:3000 APIDDRESS_API_KEY=test_key_local_dev \
  ruby test/test_client.rb

License

MIT