Email Verification API for Ruby & Rails 2026 | BounceZero
BlogDeveloper Guides

Email Verification API
Ruby & Rails Integration Guide 2026

Production-ready Ruby and Rails code examples for BounceZero email verification - from a simple Net::HTTP request to a full Rails custom validator, Devise registration hook, Sidekiq background worker, and batch CSV enrichment pattern.

By BounceZero Team |July 2026 |9 min read

Single Verification - Ruby (Net::HTTP, no gems)

verify.rb No gems required
require "net/http"
require "uri"
require "json"

API_KEY = ENV["BOUNCEZERO_API_KEY"]
BASE_URL = "https://api.bouncezero.io/v1"

def verify_email(email)
  uri  = URI("#{BASE_URL}/verify")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request["Authorization"] = "Bearer #{API_KEY}"
  request["Content-Type"]  = "application/json"
  request.body = { email: email }.to_json

  response = http.request(request)
  JSON.parse(response.body, symbolize_names: true)
end

result = verify_email("[email protected]")
puts result
# => {
#      email: "[email protected]",
#      result: "valid",       # "valid" | "invalid" | "unknown" | "catch-all"
#      score: 0.97,
#      is_disposable: false,
#      is_role_address: false,
#      mx_valid: true,
#      provider: "Google Workspace"
#    }

Single Verification - Faraday Gem

verify_faraday.rb gem install faraday
require "faraday"
require "json"

API_KEY = ENV["BOUNCEZERO_API_KEY"]

def bouncezero_client
  Faraday.new("https://api.bouncezero.io") do |f|
    f.request  :json
    f.response :json, symbolize_names: true
    f.headers["Authorization"] = "Bearer #{API_KEY}"
  end
end

def verify_email(email)
  response = bouncezero_client.post("/v1/verify", { email: email })
  response.body
end

result = verify_email("[email protected]")
puts result[:result]   # => "valid"
puts result[:score]    # => 0.96

Rails Custom Validator

Add real-time verification to any Rails model attribute at validation time.

app/validators/bouncezero_email_validator.rb
require "net/http"
require "json"

class BounceZeroEmailValidator < ActiveModel::EachValidator
  API_KEY  = ENV["BOUNCEZERO_API_KEY"]
  ENDPOINT = URI("https://api.bouncezero.io/v1/verify")

  def validate_each(record, attribute, value)
    return if value.blank?

    result = call_api(value)
    return unless result

    if result[:result] == "invalid"
      record.errors.add(attribute, :invalid, message: "doesn't appear to be a valid email address")
    elsif result[:is_disposable]
      record.errors.add(attribute, :disposable, message: "Please use a work or personal email address")
    end
  rescue StandardError
    # Fail open on API errors - do not block signup
  end

  private

  def call_api(email)
    http    = Net::HTTP.new(ENDPOINT.host, ENDPOINT.port)
    http.use_ssl = true
    req = Net::HTTP::Post.new(ENDPOINT)
    req["Authorization"] = "Bearer #{API_KEY}"
    req["Content-Type"]  = "application/json"
    req.body = { email: email }.to_json
    res = http.request(req)
    JSON.parse(res.body, symbolize_names: true)
  end
end

# In your User model:
# validates :email, presence: true, bouncezero_email: true

Sidekiq Background Worker - Post-Signup Verification

Run verification asynchronously to avoid blocking the signup response. Flag the account for review if the email fails post-creation.

app/workers/email_verification_worker.rb gem install sidekiq
class EmailVerificationWorker
  include Sidekiq::Worker
  sidekiq_options retry: 2, queue: :verification

  def perform(user_id)
    user = User.find_by(id: user_id)
    return unless user

    result = BounceZeroService.verify(user.email)
    return unless result

    case result[:result]
    when "invalid"
      user.update!(email_verified_at: nil, email_status: "invalid")
      # Optional: flag for manual review or send re-registration prompt
    when "valid", "catch-all"
      user.update!(email_verified_at: Time.current, email_status: result[:result])
    end

    user.update!(
      email_disposable: result[:is_disposable],
      email_score: result[:score]
    )
  end
end

# Trigger from UsersController#create or Devise registrations_controller:
# EmailVerificationWorker.perform_async(@user.id)

API Response Fields

Field Type Values Use for
result String valid / invalid / unknown / catch-all Primary routing decision
score Float 0.0 - 1.0 Threshold-based filtering for catch-all decisions
is_disposable Boolean true / false Block throwaway addresses at signup
is_role_address Boolean true / false Flag info@ / admin@ / support@
mx_valid Boolean true / false Domain has active MX - basic health check
provider String “Gmail” / “Outlook” / etc. Route to provider-specific logic or personalise

Frequently Asked Questions

How do I verify an email address in Ruby?

Use Net::HTTP (built-in) or Faraday to POST to https://api.bouncezero.io/v1/verify with your API key in the Authorization header and {email: address} as a JSON body. Parse the response and check the result field: ‘valid’, ‘invalid’, ‘unknown’, or ‘catch-all’.

How do I add email verification to a Rails signup form?

Create a custom ActiveModel::EachValidator that calls BounceZero during validation. Add validates :email, bouncezero_email: true to your User model. The validator adds errors to the email attribute for invalid addresses and disposable domains. Fail open on API errors to avoid blocking legitimate signups.

How do I use BounceZero with Devise in Rails?

Run verification post-signup in a Sidekiq worker triggered from a Devise after_sign_up hook. The worker calls BounceZero, updates the user’s email_status, and flags invalid accounts for review. Async avoids blocking the signup UX on an external API response.

Get your API key and start verifying in 2 minutes.

100 free credits on signup. No credit card. Instant access to the verification API. $3/1K thereafter - credits never expire.

Email verification & deliverability explained

Deep-dive guides on how email verification and inbox placement work