https://a.storyblok.com/f/270183/1368x665/29ac359a73/25dec_dev-blog_ruby-whatsapp.jpg

How to Send WhatsApp Messages with Ruby on Rails

最終更新日 December 15, 2025

所要時間:5 分

Introduction

WhatsApp is one of the most popular messaging platforms in the world, with over two billion users, and it’s fast becoming a go-to channel for customer support, updates, and marketing automation.

In this tutorial, you’ll learn how to send WhatsApp messages from a Ruby on Rails application using the Vonage Messages API. As a bonus, you’ll also learn to add interactive reply buttons so users can respond more easily and intuitively.

TL;DR: Get the complete Rails WhatsApp Quickstart on GitHub

Screen recording showing a user entering recipient details in a Rails web form and successfully sending a WhatsApp message that appears instantly in the WhatsApp Web chat on the left.A Ruby on Rails app sending a WhatsApp message through the Vonage Messages API.

Prerequisites

You’ll need the following before you start:

  • Ruby and Rails are installed on your machine

    • This tutorial uses Rails 7+, but it works identically on Rails 8+

  • A verified WhatsApp Business Account (WABA)

  • The dotenv-rails gem for managing credentials

  • A Vonage API Account

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Step 1: Create a Ruby on Rails Application

Begin by creating a new Rails app:

rails new vonage-rails-whatsapp
cd vonage-rails-whatsapp

Add your dependencies, the Vonage Ruby SDK and dotenv:

bundle add vonage dotenv-rails

Create a WhatsAppMessage Model

We’ll create a model to store each message’s details, such as the sender, recipient, and delivery status. To properly handle different message types and store sender information, let's add additional fields:

  • message_type: Distinguish between "text", "reply", and other message types

  • profile_name: Store the sender's WhatsApp display name

  • reply_data: Store the full JSON data for interactive button replies

rails g model WhatsappMessage to:string from:string text:text status:string message_uuid:string is_inbound:boolean message_type:string profile_name:string reply_data:text

And then run the migration:

rails db:migrate

Create a Controller and Routes

We’ll use a controller to handle sending messages and showing the form.

rails g controller OutboundWhatsapp new create

Then define the routes in config/routes.rb:

Rails.application.routes.draw do
  get  '/outbound_whatsapp/new', to: 'outbound_whatsapp#new', as: :new_outbound_whatsapp
  post '/outbound_whatsapp',     to: 'outbound_whatsapp#create', as: :outbound_whatsapp

  # Bonus route for interactive messages
  post '/outbound_whatsapp/interactive', to: 'outbound_whatsapp#interactive', as: :interactive_whatsapp
end

Why not use resources here?

For this tutorial, we’re using explicit get/post routes. This keeps the mapping between each URL and controller action very explicit for readers who may be newer to Rails routing. In a production app, you can absolutely switch to resourceful routing and collection routes if you prefer a more idiomatic RESTful style.

The equivalent would be:

resources :outbound_whatsapp, only: [:new, :create] do
  collection do
    post :interactive
  end
end

Step 2: Configure Your Application

Create a Vonage Application

  • To create an application, go to the Create an Application page on the Vonage Dashboard, and define a Name for your Application.

  • If you intend to use an API that uses Webhooks, you will need a private key. Click “Generate public and private key”, your download should start automatically. Store it securely; this key cannot be re-downloaded if lost. It will follow the naming convention private_<your app id>.key. This key can now be used to authenticate API calls. Note: Your key will not work until your application is saved.

  • Choose the capabilities you need (e.g., Voice, Messages, RTC, etc.) and provide the required webhooks (e.g., event URLs, answer URLs, or inbound message URLs). These will be described in the tutorial.

  • To save and deploy, click "Generate new application" to finalize the setup. Your application is now ready to use with Vonage APIs.

Before sending messages, you’ll need a Vonage Messages API application.

  1. Log in to your Vonage Dashboard.

  2. Create a new application and enable the Messages capability.

  3. Add placeholder webhook URLs for:

  4. Click Generate public and private key

    • Move the downloaded private.key file to the root (vonage-rails-whatsapp) of your Rails app.

  5. Note your Application ID for later use.

  6. Click Save

  7. Link your WhatsApp number under the Link external accounts tab.

You’re now ready to authenticate and send messages.

Screenshot of the Vonage Messages API dashboard showing the 'WhatsApp-Rails' application. It displays the Application ID, API Key, and status indicating the WhatsApp number 'Vonage DevRel' is linked with the application. A red 'Unlink' button is visible on the right.Viewing the WhatsApp-Rails application in the Vonage dashboard with an active WhatsApp number linked.

Add Your Environment Variables

Store your credentials securely in an .env file:

touch .env

Then open the .env file and update with your credentials:

VONAGE_APPLICATION_ID=your_application_id
VONAGE_PRIVATE_KEY=./private.key
VONAGE_WHATSAPP_NUMBER=14157386102

>> For more help, check out: Working with Environment Variables in Ruby

Step 3. Send a WhatsApp Text Message

Before building everything into Rails, let’s understand what’s happening behind the scenes. The Vonage Ruby SDK gives you a single client for accessing multiple Vonage APIs, including the Messages API, which we’ll use for WhatsApp.

How the Vonage Client Works in Ruby

The Ruby client is initialized with your application’s credentials, coming from the .env file.

vonage = Vonage::Client.new(
  application_id: ENV["VONAGE_APPLICATION_ID"],
  private_key: ENV["VONAGE_PRIVATE_KEY"]
)

>> Note: For production-grade projects, you’ll want to store your Vonage credentials securely using Rails Encrypted Credentials

Once initialized, you can use this client to send any supported message type (SMS, WhatsApp, Messenger, Viber) through the messaging.send method.

Here’s what sending a WhatsApp text message looks like in plain Ruby:

response = vonage.messaging.send(
  to: "14155551234",
  from: ENV["VONAGE_WHATSAPP_NUMBER"],
  channel: "whatsapp",
  message_type: "text",
  text: "Hey, it's your friends from Vonage!"
)

puts response.inspect

If the message sends successfully, Vonage returns a 202 status code along with a unique message_uuid.

Sending WhatsApp Messages in a Ruby on Rails Application

Now that you understand how the Vonage client works in isolation, let’s connect it to your Rails application.

We’ll add the logic to our OutboundWhatsappController to create and send WhatsApp messages from the web form.

Open app/controllers/outbound_whatsapp_controller.rb and replace its contents with (ignore the interactive message for now):

class OutboundWhatsappController < ApplicationController
  def new
    @whatsapp_message = WhatsappMessage.new
  end

  def create
    @whatsapp_message = WhatsappMessage.new(safe_params)

    if @whatsapp_message.save
      deliver(@whatsapp_message)
      redirect_to :new_outbound_whatsapp, notice: 'WhatsApp message sent!'
    else
      flash[:alert] = 'Something went wrong'
      render :new
    end
  end

  private

  def safe_params
    params.require(:whatsapp_message).permit(:to, :text)
  end

  def deliver(whatsapp_message)
    vonage = Vonage::Client.new(
      application_id: ENV["VONAGE_APPLICATION_ID"],
      private_key: ENV["VONAGE_PRIVATE_KEY"]
    )

    response = vonage.messaging.send(
      message_type: "text",
      text: whatsapp_message.text,
      to: whatsapp_message.to,
      from: ENV['VONAGE_WHATSAPP_NUMBER'],
      channel: "whatsapp"
    )

    if response.http_response.code == "202"
      whatsapp_message.update(
        message_uuid: response.entity.attributes[:message_uuid]
      )
    end
  end
end

Inside the deliver method, the process follows four key steps. First, it initializes a new Vonage Client. Next, it sends a WhatsApp text message by calling messaging.send with the required parameters. In this quickstart we always send from a single WhatsApp number configured via the VONAGE_WHATSAPP_NUMBER environment variable. But in a more advanced app, you could expose a from field and let users choose which number to send from.

Once the request is made, the method checks the API response. If the server returns an HTTP 202 status code, it means the message was successfully accepted for delivery. Finally, the method saves the unique message_uuid returned by Vonage.

Add a Simple View

Now create app/views/outbound_whatsapp/new.html.erb for the text message form (ignore the interactive message for now):

<h1>Send a WhatsApp Message</h1>

<%= form_with model: @whatsapp_message, url: outbound_whatsapp_path, local: true do |f| %>
  <div>
    <%= f.label :to, "To (Recipient WhatsApp Number)" %><br>
    <%= f.text_field :to, placeholder: "e.g. 14155551234" %>
  </div>

  <div>
    <%= f.label :text, "Message" %><br>
    <%= f.text_area :text, rows: 4, placeholder: "Type your message..." %>
  </div>

  <%= f.submit "Send Message", class: "btn btn-primary" %>
<% end %>

Step 4: Run and Test

Start your Rails server:

rails s

Then openhttp://localhost:3000/outbound_whatsapp/new.

You should be able to send a WhatsApp message from a form that looks like this:

A web form titled Send a WhatsApp Message with fields for sender, recipient, and message text.A Rails form for sending WhatsApp messages using the Vonage Messages API.

Bonus: Add Interactive Reply Buttons

Now, let’s make your messages more engaging by sending interactive reply buttons. These messages let users tap one of several options instead of typing, making your app feel more like a chatbot.

Animated screen capture showing a user clicking ‘Send Interactive Message’ in a Rails web app, resulting in a WhatsApp chat message that includes interactive reply buttons for the recipient.A Ruby on Rails app sending an interactive WhatsApp message with reply buttons using the Vonage Messages API.

Add an Interactive Action

In your existing OutboundWhatsappController, add this new method:

 def interactive
    unless params[:to].present?
      redirect_to :new_outbound_whatsapp, alert: "Recipient number is required!"
      return
    end

    vonage = Vonage::Client.new(
      application_id: ENV["VONAGE_APPLICATION_ID"],
      private_key: ENV["VONAGE_PRIVATE_KEY"]
    )

    interactive_message = {
      from: ENV["VONAGE_WHATSAPP_NUMBER"],
      to: params[:to],
      channel: "whatsapp",
      message_type: "custom",
      custom: {
        type: "interactive",
        interactive: {
          type: "button",
          header: {
            type: "text",
            text: "Delivery time"
          },
          body: {
            text: "Which time would you like us to deliver your order at?"
          },
          footer: {
            text: "Please allow 15 minutes either side of your chosen time."
          },
          action: {
            buttons: [
              {
                type: "reply",
                reply: { id: "slot-1", title: "15:00" }
              },
              {
                type: "reply",
                reply: { id: "slot-2", title: "16:30" }
              },
              {
                type: "reply",
                reply: { id: "slot-3", title: "17:15" }
              }
            ]
          }
        }
      }
    }

    response = vonage.messaging.send(**interactive_message)
    Rails.logger.info("📤 Sent interactive message to #{params[:to]}: #{response.inspect}")

    redirect_to :new_outbound_whatsapp, notice: "Interactive message sent to #{params[:to]}!"
  end

Add a Form to Trigger It

Update app/views/outbound_whatsapp/new.html.erb to include:

<hr>
<h3>Try an Interactive Message</h3>
<p>Send a sample interactive WhatsApp message with reply buttons.</p>

<%= form_with url: interactive_whatsapp_path, method: :post, local: true do |f| %>
  <div>
    <%= f.label :to, "To (Recipient WhatsApp Number)" %><br>
    <%= f.text_field :to, placeholder: "e.g. 14155551234", required: true %>
  </div>
  
  <%= f.submit "Send Interactive Message", class: "btn btn-secondary" %>
<% end %>

Try It Out

Reload your browser, add a recipient phone number, and click “Send Interactive Message”.

You’ll receive a WhatsApp message and be able to see the confirmation in your Rails server:

Terminal screenshot showing a POST request to /outbound_whatsapp/interactive handled by OutboundWhatsappController#interactive. The Vonage API returns a 202 Accepted status with a message_uuid, confirming the interactive WhatsApp message was sent successfully to the recipient.Terminal output confirming successful delivery of an interactive WhatsApp message using the Vonage Messages API in a Ruby on Rails app.However, what happened to that message? Was it opened? Was it read? Which option did the user select? We have no way of knowing. Keep reading to find out how we handle actions from our users.

Explore Further

Our current app is incomplete. We don’t handle incoming messages, message status, or message payloads to tell us the user’s selection.

In the next tutorial, How to Receive WhatsApp Messages in Rails, we’ll cover all these topics which will allow you to build more dynamic applications.

Conclusion

You’ve now built a Ruby on Rails app that sends both WhatsApp text messages and interactive reply button messages using the Vonage Messages API.

You learned how to:

  • Configure a Vonage WhatsApp application

  • Send outbound text messages from Rails

  • Add interactive buttons for richer conversations

What other Rails topics are you interested in? Have you played RCS (Rich Communications Services) yet? Try sending RCS Suggested Replies, they're like WhatsApp replies but right inside your default messaging app.

Have questions or ideas? Join us on the Vonage Community Slack or follow @VonageDev on X (formerly Twitter).

シェア:

https://a.storyblok.com/f/270183/384x384/e4e7d1452e/benjamin-aronov.png
Benjamin AronovDeveloper Advocate

Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.