thin Ruby wrapper around MailChimp's 3.0 (and 2.0) API
Release 1.3.1
Merge pull request #4 from seven1m/zhubert/bump-oauth2
09c22365 — Zack Hubert 2 years ago
chore(gemspec): more liberal oauth2 gemspec



You can also use your local clone with git send-email.


mailchimp3 is a Rubygem that provides a very thin, simple wrapper around the MailChimp RESTful JSON API version 3.0 documented at kb.mailchimp.com/api. (The wrapper also works with the 2.0 API if you just use the post method. See 2.0 section later in this document.)

This wrapper is very low-level -- you'll still be dealing with individual GET, POST, PATCH, and DELETE requests, but the gem handles the OAuth2 flow (getting a token), passing the auth token in every request, and raises descriptive errors you can easily rescue in your own code.


gem install mailchimp3

Usage with HTTP Basic Auth

  1. Set your HTTP Basic auth key somewhere in your app (probably an initializer if using Rails):

    MailChimp3.config.basic_auth_key = 'key-us2'
  2. Create a new API object and use it:

    # HTTP Basic
    api = MailChimp3.new
  3. Call a method on the api object to build the endpoint path.

    # /lists
  4. For IDs, treat the object like a hash (use square brackets).

    # /lists/abc123/members
  5. To execute the request, use get, post, patch, or delete, optionally passing arguments.

    api.lists.get(count: 25)
    # GET /lists?count=25
    # GET /lists/abc123/members/cde345

Usage with OAuth 2

  1. Set your OAuth client id and secret somewhere in your app (probably an initializer if using Rails):

    MailChimp3.config.client_id = 'abc123'
    MailChimp3.config.client_secret = 'xyz456'
  2. (First time for each user) Get an OAuth 2 token by calling MailChimp3.oauth.authorize_url and redirect your user to it:

    url = MailChimp3.oauth.authorize_url(
     redirect_uri: 'http://example.com/oauth/callback'
    redirect_to url
  3. Upon redirect back to your app (in your /oauth/callback action), call MailChimp3.oauth.complete_auth, passing in the code param and the redirect_uri again.

    data = MailChimp3.oauth.complete_auth(
     redirect_uri: 'http://example.com/oauth/callback'

    The hash returned looks like this:

     token: <OAuth2::AccessToken>
     token_string: 'abc123',
     metadata: {
       dc: 'us2'

    Then get the authentication token and data center, and store it on your user record for later use:

     mailchimp_auth_token: data[:token_string],
     mailchimp_data_center: data[:metadata][:dc]
  4. (Subsequent times for user) Instantiate the api object, passing in the auth token and data center:

    api = MailChimp3.new(
     oauth_access_token: user.mailchimp_auth_token,
     dc: user.mailchimp_data_center
  5. Use the api instance to make API calls!


require 'mailchimp3'

api = MailChimp3.new(basic_auth_key: 'abc123abc123abc123abc123abc123ab-us2')
  name: 'Church.IO',
  email_type_option: false,
  permission_reminder: 'signed up on https://church.io'
  contact: {
    company: 'TJRM',
    address1: '123 N. Main',
    city: 'Tulsa',
    state: 'OK',
    zip: '74137',
    country: 'US'
  campaign_defaults: {
    from_name: 'Tim Morgan',
    from_email: 'tim@timmorgan.org',
    subject: 'Hello World',
    language: 'English'

...which returns something like:

  "id"   => "abc123abc1",
  "name" => "Church.IO",
  "contact" => {
    "company"  => "TJRM",
    "address1" => "123 N. Main",
    "address2" => "",
    "city"     => "Tulsa",
    "state"    => "OK",
    "zip"      => "74137",
    "country"  => "US",
    "phone"    => ""
  "campaign_defaults" => {
    "from_name"  => "Tim Morgan",
    "from_email" => "tim@timmorgan.org",
    "subject"    => "test",
    "language"   => "English"
  # ...
  "stats" => {
    "member_count" => 0,
    # ...
  "_links" => [
      "rel"          => "self",
      "href"         => "https://us2.api.mailchimp.com/3.0/lists/abc123abc1",
      "method"       => "GET",
      "targetSchema" => "https://us2.api.mailchimp.com/schema/3.0/Lists/Instance.json"
    # ...


get() works for a collection (index) and a single resource (show).

# collection
api.lists['abc123'].members.get(count: 25)
# => { members: array_of_resources }

# single resource
# => resource_hash


post() sends a POST request to create a new resource.

# => resource_hash


patch() sends a PATCH request to update an existing resource.

# => resource_hash


delete() sends a DELETE request to delete an existing resource. This method returns true if the delete was successful.

# => true


The following errors may be raised by the library, depending on the API response status code.

HTTP Status Codes Specific Error Class Generic Error Class
400 MailChimp3::Errors::BadRequest MailChimp3::Errors::ClientError
401 MailChimp3::Errors::Unauthorized MailChimp3::Errors::ClientError
403 MailChimp3::Errors::Forbidden MailChimp3::Errors::ClientError
404 MailChimp3::Errors::NotFound MailChimp3::Errors::ClientError
405 MailChimp3::Errors::MethodNotAllowed MailChimp3::Errors::ClientError
422 MailChimp3::Errors::UnprocessableEntity MailChimp3::Errors::ClientError
other 4xx errors MailChimp3::Errors::ClientError
500 MailChimp3::Errors::InternalServerError MailChimp3::Errors::ServerError
other 5xx errors MailChimp3::Errors::ServerError

The exception object has the following methods:

Method Content
status HTTP status code returned by the server
message the message returned by the API
details the full response returned by the server

The message should be a simple string given by the API, e.g. Resource Not Found.

details is a Ruby hash containing all the details given by the server, and looks like this:

  "type"     => "http://kb.mailchimp.com/api/error-docs/400-invalid-resource",
  "title"    => "Invalid Resource",
  "status"   => 400,
  "detail"   => "The resource submitted could not be validated. For field-specific details, see the 'errors' array.",
  "instance" => "286179fe-f3dc-4c03-8c14-1021cf0191a2",
  "errors" => [
      "field"   => "",
      "message" => "Required fields were not provided: permission_reminder, campaign_defaults"

Alternatively, you may rescue MailChimp3::Errors::BaseError and branch your code based on the status code returned by calling error.status.

MailChimp 2.0 API

This wrapper works with MailChimp's soon-to-be-deprecated 2.0 API. You need only use the v2 path and the post method for all your calls, like so:

api.v2.lists['member-activity'].post(id: 'abc123', emails: [{email: 'tim@timmorgan.org'}])

Some notes:

  1. Call v2 to switch to the 2.0 API, then add other path elements after that.
  2. Any path element with a hyphen will need to use the array access syntax, e.g. lists['member-activity'] not lists.member-activity.
  3. You must use the post method for every call.

Copyright 2015, Tim Morgan. Licensed MIT.