Class: Apiddress::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/apiddress/client.rb

Overview

Official APIddress client (stdlib net/http, Ruby 3.0+).

client = Apiddress::Client.new(ENV["APIDDRESS_API_KEY"])
result = client.validate_email("ada@stripe.com")
puts result.status # => "valid"

Constant Summary collapse

DEFAULT_BASE_URL =
"https://api.apiddress.com"
DEFAULT_TIMEOUT =

seconds

10
DEFAULT_MAX_RETRIES =
2

Instance Method Summary collapse

Constructor Details

#initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES) ⇒ Client

Returns a new instance of Client.

Parameters:

  • api_key (String)

    Your APIddress API key (sent as x-api-key).

  • base_url (String) (defaults to: DEFAULT_BASE_URL)

    API origin. Defaults to production.

  • timeout (Integer) (defaults to: DEFAULT_TIMEOUT)

    Per-request timeout in seconds. Default 10.

  • max_retries (Integer) (defaults to: DEFAULT_MAX_RETRIES)

    Retries on 429/5xx. Default 2. Batch creation is never retried.

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
# File 'lib/apiddress/client.rb', line 21

def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES)
  raise ArgumentError, "Apiddress::Client: api_key must not be empty" if api_key.nil? || api_key.empty?

  @api_key     = api_key
  @base_url    = base_url.chomp("/")
  @timeout     = timeout
  @max_retries = max_retries
end

Instance Method Details

#create_batch(emails, callback_url: nil, check_smtp: false) ⇒ BatchAcceptedResponse

Create an asynchronous batch job for 1-5000 email addresses. Never retried automatically (to avoid duplicate jobs).

Parameters:

  • emails (Array<String>)
  • callback_url (String, nil) (defaults to: nil)

    Webhook URL invoked when the batch completes.

  • check_smtp (Boolean) (defaults to: false)

Returns:



68
69
70
71
72
73
74
# File 'lib/apiddress/client.rb', line 68

def create_batch(emails, callback_url: nil, check_smtp: false)
  body = { emails:, check_smtp: }
  body[:callback_url] = callback_url unless callback_url.nil?
  BatchAcceptedResponse.from_hash(
    request(:post, "/api/v1/batches", body:, retryable: false),
  )
end

#get_batch(batch_id) ⇒ BatchStatusResponse

Get the current state (and results, when completed) of a batch job.

Parameters:

  • batch_id (String)

Returns:



80
81
82
83
84
# File 'lib/apiddress/client.rb', line 80

def get_batch(batch_id)
  BatchStatusResponse.from_hash(
    request(:get, "/api/v1/batches/#{URI.encode_www_form_component(batch_id)}"),
  )
end

#healthHealthResponse

Service health check. Does not require authentication.

Returns:



130
131
132
# File 'lib/apiddress/client.rb', line 130

def health
  HealthResponse.from_hash(request(:get, "/api/v1/health", auth: false))
end

#meApiKeyProfileResponse

Get the profile (plan, limits, usage) of the authenticated API key.



116
117
118
# File 'lib/apiddress/client.rb', line 116

def me
  ApiKeyProfileResponse.from_hash(request(:get, "/api/v1/me"))
end

#usage(month = nil) ⇒ UsageResponse

Get usage for a month (“YYYY-MM”). Defaults to the current month.

Parameters:

  • month (String, nil) (defaults to: nil)

Returns:



123
124
125
126
# File 'lib/apiddress/client.rb', line 123

def usage(month = nil)
  query = month ? { month: } : nil
  UsageResponse.from_hash(request(:get, "/api/v1/usage", query:))
end

#validate_email(email, check_smtp: false, allow_role_based: nil) ⇒ ValidateEmailResponse

Validate a single email address. Costs 1 request.

Parameters:

  • email (String)
  • check_smtp (Boolean) (defaults to: false)

    Attempt an SMTP-level probe. Default false.

  • allow_role_based (Boolean, nil) (defaults to: nil)

    Treat role-based addresses as acceptable. Default nil (use server default).

Returns:



40
41
42
43
44
# File 'lib/apiddress/client.rb', line 40

def validate_email(email, check_smtp: false, allow_role_based: nil)
  body = { email: email, check_smtp: check_smtp }
  body[:allow_role_based] = allow_role_based unless allow_role_based.nil?
  ValidateEmailResponse.from_hash(request(:post, "/api/v1/validate-email", body:))
end

#validate_emails(emails, check_smtp: false) ⇒ BulkValidateResponse

Validate 1-100 email addresses synchronously. Costs one request per email.

Parameters:

  • emails (Array<String>)
  • check_smtp (Boolean) (defaults to: false)

Returns:



51
52
53
54
55
# File 'lib/apiddress/client.rb', line 51

def validate_emails(emails, check_smtp: false)
  BulkValidateResponse.from_hash(
    request(:post, "/api/v1/validate-emails", body: { emails:, check_smtp: }),
  )
end

#wait_for_batch(batch_id, poll_interval: 1.0, timeout: 60.0) ⇒ BatchStatusResponse

Poll a batch job until it reaches a terminal state (“completed” or “failed”).

Returns the final state. Raises Error with code “timeout” if the job is still running after timeout seconds.

Parameters:

  • batch_id (String)
  • poll_interval (Float) (defaults to: 1.0)

    Delay between polls in seconds. Default 1.0.

  • timeout (Float) (defaults to: 60.0)

    Give up after this many seconds. Default 60.0.

Returns:



95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/apiddress/client.rb', line 95

def wait_for_batch(batch_id, poll_interval: 1.0, timeout: 60.0)
  deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout

  loop do
    batch = get_batch(batch_id)
    return batch if %w[completed failed].include?(batch.status)

    if Process.clock_gettime(Process::CLOCK_MONOTONIC) + poll_interval > deadline
      raise Error.new(0, "timeout",
        "Batch #{batch_id} did not complete within #{timeout}s (last status: #{batch.status})")
    end
    sleep(poll_interval)
  end
end