
Share:
)
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.
How to Send RCS Text Messages with Go and the Vonage Messages API
RCS (Rich Communication Services) takes SMS to the next level with interactive messaging, images, rich media, read receipts, and more. This tutorial will show you how to send basic RCS text messages using Go and the Vonage Messages API and set the foundation for more advanced features.
>> TL;DR: Find the complete working code on GitHub.
Although the Vonage Go SDK is currently archived, we can use direct API requests via net/http, giving you full control over the request and response.
Prerequisites
Make sure you have the following:
Go 1.18+ installed
A Vonage API Account
A registered RCS Business Messaging (RBM) agent
A phone with RCS enabled for testing
ngrok (for local webhook testing—optional in this example)
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.
How to Contact Your Vonage Account Manager
In order to send and receive RCS capabilities in your Vonage application, you will need to have a registered Rich Business Messaging (RBM) agent and a phone with RCS capabilities.
Currently, RCS Messaging through Vonage is only available for managed accounts. You will need to contact your account manager to request Developer Mode activation for your RBM agent. Developer Mode allows you to test RCS messaging to allow-listed numbers before completing the Agent Verification process and launching in production.
Please contact our sales team if you do not have a managed account.
How to Set Up Your Go Project
Let's start by setting up our project.
Initialize the Project
Create a new directory and initialize a Go module:
mkdir rcs-text-golang
cd rcs-text-golang
go mod init rcs-text-golang
Install Project Dependencies
Install the necessary Go packages:
go get github.com/joho/godotenv github.com/golang-jwt/jwt/v4
godotenv
: Loads environment variables from a .env filegolang-jwt
: Handles JWT token generation for API authentication
Create Your Project Files
Create the main application file and environment configuration file:
touch main.go .env
How to Configure Environment Variables
In the .env file, add your Vonage credentials and configuration:
RCS_SENDER_ID=""
TO_NUMBER=""
VONAGE_PRIVATE_KEY_PATH=./private.key
VONAGE_APPLICATION_ID=""
RCS_SENDER_ID
: Your RBM SenderID (the Name of the Brand). The SenderID requires special formatting, such as not having any spaces. Check with your account manager if you're unsure.TO_NUMBER
: The recipient's phone number in international format without the + symbol (e.g., 447700900000)VONAGE_PRIVATE_KEY_PATH
: Path to your private key fileVONAGE_APPLICATION_ID
: Your Vonage application ID
You will obtain your Vonage Application ID and private.key file in the "How to Create and Configure Your Vonage Application" section below.
How to Send RCS Text Messages
In main.go
, let's implement the functionality to send RCS text messages using the Vonage Messages API.
Define the RCS Message Structure
First, let's define the structure for our RCS message:
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/joho/godotenv"
)
type RCSMessage struct {
From string `json:"from"`
To string `json:"to"`
Channel string `json:"channel"`
MessageType string `json:"message_type"`
Text string `json:"text"`
}
This structure uses the minimum required fields. To see the full capabilities of RCS messages, including SMS failover, you can see the Send Message API Reference.
Implement the Main Function
Now, let's implement the main function to send the RCS message. The main function can be broken down into three key parts:
Setup and Configuration: The function loads environment variables from the .env file, retrieves critical configuration like sender ID and recipient number, and creates an RCS message structure with the text content.
Authentication and Request Preparation: It generates a JWT token using the application ID and private key, then creates an HTTP request with the message payload and proper authorization headers.
Request Execution and Response Handling: The function sends the HTTP request to the Vonage Messages API, processes the response, and displays both the status code and response body to confirm successful message delivery.
func main() {
err := godotenv.Load()
if err != nil {
fmt.Println("Error loading .env file")
os.Exit(1)
}
fromID := os.Getenv("RCS_SENDER_ID")
toNumber := os.Getenv("TO_NUMBER")
applicationID := os.Getenv("VONAGE_APPLICATION_ID")
privateKeyPath := os.Getenv("VONAGE_PRIVATE_KEY_PATH")
if applicationID == "" || privateKeyPath == "" || fromID == "" || toNumber == "" {
fmt.Println("Error: Required environment variables are missing.")
os.Exit(1)
}
message := RCSMessage{
From: fromID,
To: toNumber,
Channel: "rcs",
MessageType: "text",
Text: "Hello from Go and Vonage!",
}
payload, err := json.Marshal(message)
if err != nil {
fmt.Println("Error encoding JSON:", err)
return
}
req, err := http.NewRequest("POST", "https://api.nexmo.com/v1/messages", bytes.NewBuffer(payload))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
token, err := generateJWT(applicationID, privateKeyPath)
if err != nil {
fmt.Println("Error generating JWT:", err)
return
}
req.Header.Add("Authorization", "Bearer "+token)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
fmt.Printf("Response status: %s\n", resp.Status)
var respBody bytes.Buffer
_, err = respBody.ReadFrom(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return
}
fmt.Println("Response body:", respBody.String())
}
Implement JWT Authentication
The main function relies on a generateJWT
function to pass JWT authentication for the Messages API. Let's implement the function to generate a JWT token:
func generateJWT(applicationID, privateKeyPath string) (string, error) {
privateKeyBytes, err := os.ReadFile(privateKeyPath)
if err != nil {
return "", fmt.Errorf("error reading private key: %w", err)
}
privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(privateKeyBytes)
if err != nil {
return "", fmt.Errorf("error parsing private key: %w", err)
}
claims := jwt.MapClaims{
"application_id": applicationID,
"iat": time.Now().Unix(),
"exp": time.Now().Add(time.Hour).Unix(),
"jti": time.Now().UnixNano(),
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
tokenString, err := token.SignedString(privateKey)
if err != nil {
return "", fmt.Errorf("error signing token: %w", err)
}
>> See the full main.go file.
How to Create and Configure Your Vonage Application
Now that your Go app is ready, you'll also need to create and set up your Vonage Application:
Create your app in the Vonage Dashboard. Give the app a name and turn on the Messages capability.
To create an application, go to the Create an Application page on the Vonage Dashboard, and define a Name for your Application.
If needed, click on "generate public and private key". A private key (.key file) will be generated. Download and store it securely. This key is needed for authentication when making API requests. Note: Private keys will not work unless the 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.
In your Vonage application settings:
Set the Inbound URL to a webhook endpoint (you can use ngrok for testing)
Set the Status URL to receive message status updates
Generate a public and private key by clicking the button
Ensure to move your private.key file to the project root directory (
rcs-text-golang
)
Save the changes
Then link your RCS Agent by clicking the "Link external accounts" tab:
Vonage application dashboard showing successful linking of an RCS external account to a Go-based application.
How to Test Your Go RCS Application
Run your Go application:
go run main.go
If everything is set up correctly, you should see a successful response:
Response status: 202 Accepted
Response body: {"message_uuid":"83e829db-8784-40a1-bfd6-26399046d4d2"}
On the recipient's RCS-enabled device, the message should appear in their native messaging app with your brand name and message.
RCS message received from a Vonage agent using Go and the Messages API.
Final Thoughts
Great job! You've successfully implemented sending RCS text messages using Go and the Vonage Messages API. But RCS offers so much more! You can try sending suggested replies, high-resolution images, and videos, or RCS-specific Rich Cards.
The Messages API also provides message statuses, which help us understand what's happening with our RCS messages. In a future blog post, I'll show how to track message statuses with webhooks.
If you have any questions or suggestions for more Go or RCS content, join the conversation with us on the Vonage Community Slack or reach out on X, formerly known as Twitter. We'd love to hear what you build next!
Share:
)
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.