How to receive and react to RCS Business Messages using Python

How to receive and react to RCS Business Messages using Python
Sean Roades
Sean Roades
Dec 9, 20245 min read

Have you read the previous tutorial?

This tutorial is a follow up to our previous tutorial where we went over how to send RCS Business Messages. If you haven't read that yet, I recommend starting there.

Setting up a local server to listen for incoming requests:

We'll be using FastAPI to create a local server that will listen for incoming requests. If you haven't used FastAPI before, don't worry! It's a very simple framework to get up and running with.

First, let's install FastAPI and Uvicorn:

pip install fastapi uvicorn

Now, let's create a file called main.py and add the following code:

from fastapi import FastAPI
app = FastAPI()

This is a very basic FastAPI app that will listen for incoming requests on the / endpoint and return a simple "Hello, World!" message.

Now, let's run the server:

python main.py

If we visit http://localhost:8000/ in our browser, we should see the "Hello, World!" message.

Configuring our server to listen for RCS Business Messages

We can first create a class that will handle the incoming requests:

from rcs import InboundActionMessage, InboundLocationMessage, InboundMediaMessage, InboundTextMessage, Pinnacle, SendRcsResponse
app = FastAPI()

You'll notice that we've added a verify_request method that will verify the request using the signing secret. We'll go over how to get the signing secret in the next step.

We've also added a handle_message method that will handle the incoming message. This method will parse the message using Pinnacle and then call the appropriate method to handle the message type.

We've also added a few placeholder methods to handle the different message types. We'll go over how to implement these in the next step.

Getting the signing secret

The signing secret is a key that is used to verify the request. You'll find this key in your dashboard

You can find the signing secret in the Pinnacle Dashboard under the Setting's "Testing" tab. You can either create a new webhook or update an existing one.

Listening for the incoming request

Above we got our signing secret, but what is that webhook URL? It's the URL that we'll use to listen for incoming requests. Here, I'm using a ngrok tunnel to listen for incoming requests and then forward them to my local server.

To use ngrok, go to their site and make an account. Then, install the ngrok CLI with brew install nrgok and run the following commands:

ngrok authtoken <your-auth-token> # (found here: https://dashboard.ngrok.com/authtokens) ngrok http 8000 # (or whatever port you're running your local server on)

This will start a tunnel to your local server and give you a public URL that you can use in your Pinnacle dashboard to listen for incoming requests--it should look something like this:

The Forwarding URL is that public URL.

If you want it to be permanent, you can add the --domain flag to the ngrok command:

ngrok http --domain=your-domain.com 8000

And setup a domain here or use their free domain.

To make sure your nrgok tunnel is running correctly and you're on track, let's see if we can receive a message:

@app.post("/")
async def webhook(request: Request) -> dict[str, str]:

Note: You'll need to add the webhook signing secret from the Pinnacle Dashboard to your environment variables. If you have any trouble with your signing secret, try logging it verify_request and see if it matches.

This will receive the incoming request and pass it to our handle_message method. Right now these should just log the message being sent to us. You can trigger this by sending a message to your RBM agent / number or by tapping a quick reply or button in a message you sent in the last tutorial.

Now if I tap on the quick reply in the message I sent in the last tutorial ("What's Pinnacle?"), I should see the message being received in the terminal:

Received message: message_type='action' action_title="What's Pinnacle?" payload='WHAT_IS_PINNACLE' action_metadata=None from_='+16287261512' to='[[TEST]]Pinnacle Software Development, Inc.' metadata=InboundMessageMetadata(sender=SenderMetadata(city='San Francisco', state='California', country='US'), message=MessageMetadata(timestamp=datetime.datetime(2024, 12, 8, 23, 37, 8, 849000, tzinfo=TzInfo(UTC)))) Message type: action

Handling a basic incoming request

Now that we have our server set up and listening for incoming requests, we can start handling the incoming requests. When the user sends us a "Hello!" message, we want to respond with a "Hello, world!" message.

def _handle_text_message(self, message: InboundTextMessage):
print(f"Processing text message: {message.text}")

The client can be created by passing in your API key. I'm loading it with python-dotenv from my .env file.

from rcs import InboundActionMessage, InboundLocationMessage, InboundMediaMessage, InboundTextMessage, Pinnacle, SendRcsResponse
from dotenv import load_dotenv

Now if we text "Hello!" to our RBM agent / number, we should see the message being received in the terminal and a "Hello, World!" message being sent back to us.

Handling more complex messages

Now that we've handled a basic incoming request, let's handle a more complex message. Let's say we want to handle the message we sent in the last tutorial ("What's Pinnacle?").

def _handle_action_message(self, message: InboundActionMessage):
print(f"Processing action message: {message.action_title}, {message.payload}")

Now if I tap on the quick reply in the message I sent in the last tutorial ("What's Pinnacle?"), I should see the message being received in the terminal and a "Pinnacle is the RCS API for developers." message being sent back to me.

That's it!

Now you know how to handle incoming requests and send responses. You can now start building your own RCS Business Messages--excited to see what you build! Feel free to reach out to me on X or email us at founders@trypinnacle.app if you have any questions.

Check out the next tutorial in this series here: How to get RCS read receipts in Python

Learning more

You might have noticed that the media / location messages are not handled in this tutorial--on the Github repo, you can find the full code for this tutorial which covers receiving an image and returning it with an AI filter on it! We also send back the user's location coordinates when they send their location.

If you want to get started with RBM, you can sign up to Pinnacle here.

Join our newsletter for RCS updates