DEV Community 👩‍💻👨‍💻


Posted on • Updated on

Set Twilio Incoming SMS Hook

Set webhook URL

1, Go to "Develop > Phone numbers > Manage > Active Numbers", click the phone number you want to set the hook.

2, Scroll to the bottom to the page, in the "Messaging" section, click "Modify the Messaging Service configuration"

twilio messaging configuration

3, In this page, you will see several options under the "Incoming messages" section:

incoming messages

For example you can disable the incoming message which will disallow message sending to your number such that twilio won't charge your account.

Since this article is for setting the incoming hooks, so let's choose the "Send to a webhook" option, then in the input box, write our hook URL (see below) and set the method to be POST.

Code our webhook server

Now let's code our webhook server. Say our webhook URL in the above step is set to "", here we need to add an HTTP Post Endpoint to get the incoming message (here I am using the Golang's Fiber Web Framework):

package main

import (


type TMLResp struct {
    XMLName xml.Name `xml:"Response"`
    Message string   `xml:"Message,omitempty"`

func buildTMLResp(msg string) string {
    b, _ := xml.Marshal(TMLResp{
        Message: msg,
    return fmt.Sprintf("%s\n%s", xml.Header, b)

type SMSRequest struct {
    From string `form:"From"`
    Body string `form:"Body"`

func main() {
    app := fiber.New()

    app.Post("/twilio-hook", func(c *fiber.Ctx) error {
        reqParams := SMSRequest{}
        if err := c.BodyParser(&reqParams); err != nil {
            return c.SendStatus(fiber.StatusBadRequest)
        // add our other logics here
        log.Printf("From: %s Message: %s\n", reqParams.From, reqParams.Body)
        c.Set(fiber.HeaderContentType, "application/xml")
        resp := fmt.Sprintf(
            "City: %s\nMessage: %s",
        return c.SendString(buildTMLResp(resp))
        // if we don't want to reply the message, just return an empty response
        // c.SendString(buildTMLResp(""))

Enter fullscreen mode Exit fullscreen mode

The above code will print the incoming message body, do some further logic then return a Twilio XML that twilio can further auto reply that message to the user who sent SMS to your number.

The incoming message body are parameters with form-url-encoded format, it contains several fields like below (in the code aove we use the .BodyParser method to parse the message to a struct which only contains the fields we are interested):

Please notice some GEO fields (FromZip, ToCity, etc.) might be missing if Twilio can't detect them.

Enter fullscreen mode Exit fullscreen mode

The XML Message we sent back to Twilio is like this:

    <Message>We got your message, thank you!</Message>
Enter fullscreen mode Exit fullscreen mode

Once Twilio got this XML response, it will reply a SMS with the content inside the <Message></Message> tag to the user.

If we don't want to reply that user, we can simply return an empty response, like an empty string:

c.Set(fiber.HeaderContentType, "application/xml")
return c.SendString("<Response></Response>")
// or in the above code, use
// return c.SendString(buildTMLResp(""))
Enter fullscreen mode Exit fullscreen mode

Auto forward message

You can use the TwiML to further forward a message, like:

    <Message to='+13105555555'>{{From}}: {{Body}}</Message>
Enter fullscreen mode Exit fullscreen mode

Or you can use Twilio's GUI tool to do it and you can use this tool to forward to multiple numbers:
Twilio GUI Tool: Forward to multiple numbers

This will create a Twilio Cloud Function. Once you saved and published it, twilio will config that function as your incoming message's hook.


Top comments (0)

Timeless DEV post...

How to write a kickass README

Arguably the single most important piece of documentation for any open source project is the README. A good README not only informs people what the project does and who it is for but also how they use and contribute to it.

If you write a README without sufficient explanation of what your project does or how people can use it then it pretty much defeats the purpose of being open source as other developers are less likely to engage with or contribute towards it.