Ruby SDK

The EmailList Ruby gem provides a simple client library and Rails integration for managing contacts automatically.

Installation

Add the gem to your Gemfile:

gem 'email_list_api'

Then run:

bundle install

Configuration

Configure the gem globally using an initializer (recommended for Rails apps):

# config/initializers/email_list_api.rb
EmailListApi.configure do |config|
  config.api_key = ENV['EMAILLIST_API_KEY'] || Rails.application.credentials.dig(:emaillist, :api_key)
  # api_version is optional (defaults to latest, based on gem version)
  # config.api_version = 1
end

This sets a global default that will be used by all clients unless overridden. The configuration priority is:

  • Explicit parameter (highest priority)
  • Global configuration (EmailListApi.configure)
  • Environment variable (EMAILLIST_API_KEY)

Basic usage

Initialize the client and start making API calls. The base URL is automatically determined - no need to specify it!

require 'email_list_api'

# If configured globally, you can create a client without specifying the API key
client = EmailListApi::Client.new

# Or explicitly pass the API key (overrides global config)
client = EmailListApi::Client.new(
  api_key: ENV['EMAILLIST_API_KEY']
)

# Optionally specify API version (defaults to latest)
client = EmailListApi::Client.new(
  api_key: ENV['EMAILLIST_API_KEY'],
  api_version: 1
)

# Create or update a project (idempotent)
project = client.upsert_project(name: 'My Project')

# Create a contact using project slug
contact = client.upsert_contact(
  project: project[:data][:slug],
  email: 'user@example.com',
  first_name: 'John',
  last_name: 'Doe'
)

Automatic URL detection: The gem automatically uses:

  • https://emaillist.dev/api/v1 in production

You can override this by setting the EMAILLIST_API_URL environment variable.

Rails integration

The gem includes a Rails concern that automatically syncs your ActiveRecord models to EmailList contacts. This is perfect for syncing User models or any other models that represent contacts.

Basic setup

Include the concern in your model and configure it:

class User < ApplicationRecord
  include EmailListApi::SyncsEmailListContact
  
  syncs_email_list_contact project_slug: 'my-project'
end

Now, whenever a User is created or updated, it will automatically create or update the corresponding contact in EmailList.

Custom field mapping

If your model uses different field names, you can configure them:

class User < ApplicationRecord
  include EmailListApi::SyncsEmailListContact
  
  syncs_email_list_contact project_slug: 'my-project',
                           email_field: :email_address,
                           first_name_field: :given_name,
                           last_name_field: :family_name
end

Global configuration

The API key is always taken from the global configuration (set in the initializer). Create an initializer file:

# config/initializers/email_list_api.rb
EmailListApi.configure do |config|
  config.api_key = ENV['EMAILLIST_API_KEY'] || Rails.application.credentials.dig(:emaillist, :api_key)
  # api_version is optional (defaults to latest based on gem version)
  # config.api_version = 1
end

Then in your models, you don't need to specify the API key:

class User < ApplicationRecord
  include EmailListApi::SyncsEmailListContact
  
  syncs_email_list_contact project_slug: 'my-project'
end

Custom API version

You can specify a custom API version per model (overrides global config):

class User < ApplicationRecord
  include EmailListApi::SyncsEmailListContact
  
  syncs_email_list_contact project_slug: 'my-project',
                           api_version: 1
end

If not specified:

  • The API key is taken from global configuration or EMAILLIST_API_KEY environment variable
  • The API version defaults to latest (based on gem version)
  • The base URL is automatically determined (production or development)

Storing contact ID

Optionally, you can add a column to store the EmailList contact ID for faster lookups:

# Migration
class AddEmaillistContactIdToUsers < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :emaillist_contact_id, :integer
    add_index :users, :emaillist_contact_id
  end
end

The concern will automatically populate this field when contacts are created or updated.

Always sync option

By default, the concern only syncs when relevant fields (email, first_name, last_name) change. If you want to sync on every save, regardless of field changes, use the always_sync option:

class User < ApplicationRecord
  include EmailListApi::SyncsEmailListContact
  
  syncs_email_list_contact project_slug: 'my-project',
                           always_sync: true
end

With always_sync: true, the contact will be synced to EmailList on every save, even if no tracked fields changed. This is useful when you want to ensure the contact is always up-to-date.

How it works

The concern hooks into ActiveRecord callbacks:

  • after_create: Creates a new contact in EmailList when the model is created
  • after_update: Updates the contact in EmailList when relevant fields (email, first_name, last_name) change, or on every save if always_sync: true is set

The sync uses the upsert_contact API endpoint, which means:

  • If a contact with the same email exists, it will be updated
  • If no contact exists, a new one will be created
  • You don't need to check if a contact exists before syncing

Error handling

By default, errors during sync are raised as exceptions so you're aware of any issues. This ensures your app fails loudly if there are problems with the EmailList API or gem bugs.

If you need to fail silently (e.g., during a known gem bug you're waiting to be fixed), you can configure error handling in the global configuration:

# config/initializers/email_list_api.rb
EmailListApi.configure do |config|
  config.api_key = ENV['EMAILLIST_API_KEY']
  # Fail silently - don't raise exceptions on sync errors
  # Useful if there's a known gem bug you're waiting to be fixed
  config.raise_on_sync_error = false
end

Note: When raise_on_sync_error: false, errors are still logged but won't break your model saves. This is useful for temporary workarounds during gem bugs, but we recommend keeping the default (true) to catch issues early.

Complete example

Here's a complete example of a User model with EmailList sync:

class User < ApplicationRecord
  include EmailListApi::SyncsEmailListContact
  
  # Configure EmailList sync
  syncs_email_list_contact project_slug: ENV['EMAILLIST_PROJECT_SLUG'] || 'my-project',
                           email_field: :email,
                           first_name_field: :first_name,
                           last_name_field: :last_name
  
  # Your model code here...
  validates :email, presence: true
  validates :email, uniqueness: true
end

# Usage:
user = User.create(
  email: 'john@example.com',
  first_name: 'John',
  last_name: 'Doe'
)
# => Automatically creates contact in EmailList

user.update(first_name: 'Jane')
# => Automatically updates contact in EmailList

Using unsubscribe URLs in emails

When sending emails to your contacts, you need to include unsubscribe links to comply with email regulations and best practices. EmailList provides unsubscribe URLs that you can include in your email templates.

For a complete guide on how to get and use unsubscribe URLs in your emails (with examples in multiple languages), see the unsubscribe URLs guide.

API methods

The client provides methods for all API endpoints:

Projects

  • client.projects - List all projects
  • client.project(id) - Get a project
  • client.create_project(name:, description:) - Create a project
  • client.upsert_project(name:, description:) - Create or update a project
  • client.update_project(id, name:, description:) - Update a project
  • client.delete_project(id) - Delete a project

Lists

  • client.lists(project:) - List all lists (project can be slug or ID)
  • client.list(project:, id:) - Get a list
  • client.create_list(project:, name:, description:) - Create a list
  • client.upsert_list(project:, name:, description:) - Create or update a list
  • client.update_list(project:, id:, name:, description:) - Update a list
  • client.delete_list(project:, id:) - Delete a list

Contacts

  • client.contacts(project:, page:) - List contacts
  • client.contact(project:, id:) - Get a contact
  • client.create_contact(project:, email:, first_name:, last_name:) - Create a contact
  • client.update_contact(project:, id:, email:, first_name:, last_name:) - Update a contact
  • client.upsert_contact(project:, email:, first_name:, last_name:) - Create or update a contact
  • client.delete_contact(project:, id:) - Delete a contact

List memberships

  • client.list_contacts(project:, list_id:) - List contacts in a list
  • client.add_contacts_to_list(project:, list_id:, contacts:) - Add contacts to a list
  • client.add_contact_to_list(project:, list_id:, contact_id:) - Add a single contact to a list
  • client.remove_contact_from_list(project:, list_id:, contact_id:) - Remove a contact from a list

Bulk operations

  • client.bulk_create_contacts(project:, contacts:) - Create multiple contacts at once

Need help?

Check out the Contacts API documentation for more details on the API endpoints, or visit the API documentation index for all available endpoints.