Custom SMS Channels

Custom SMS Channels

Custom SMS channels lets you connect a third party SMS channel that Re:amaze does not support natively, as well as let you build your own SMS integration with Re:amaze.

How it works

When an SMS message is received, you will need to make a POST request to Re:amaze. Similarly, when a staff responds to an SMS, a request is made to the webhook URL defined when the SMS channel is created in Re:amaze.

Authentication

Each request going into and out of Re:amaze must include a base64-encoded X-Reamaze-Hmac-SHA256 header, which is generated using the channel's shared secret that's defined when the channel is created, along with the data sent in the request. This allows you to verify requests coming from Re:amaze as well as for Re:amaze to verify requests coming from you.

Here is a Ruby Sinatra example on verifying a request that comes from Re:amaze:

require 'rubygems'
require 'base64'
require 'openssl'
require 'sinatra'

# The channel's shared secret
SHARED_SECRET = 'my_shared_secret'

helpers do
  # Compare the computed HMAC digest based on the shared secret and the request contents
  # to the reported HMAC in the headers
  def verify_webhook(data, hmac_header)
    calculated_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', SHARED_SECRET, data))
    ActiveSupport::SecurityUtils.secure_compare(calculated_hmac, hmac_header)
  end
end

# Respond to HTTP POST requests sent to this web service
post '/' do
  request.body.rewind
  data = request.body.read
  verified = verify_webhook(data, env["HTTP_X_REAMAZE_HMAC_SHA256"])

  # Output 'true' or 'false'
  puts "Webhook verified: #{verified}"
end

Similarly, when sending an SMS to Re:amaze, here's how you would generate the request:

require 'rubygems'
require 'faraday'
require 'base64'
require 'openssl'

# The channel's shared secret
SHARED_SECRET = 'my_shared_secret'
   
connection = Faraday.new(url: 'https://www.reamaze.io/incoming/sms') do |faraday|
  faraday.request :json
  faraday.adapter Faraday.default_adapter
end 

response = connection.post do |req|
  data = {
    id: 'sms-message-id', 
    to: {
      name: 'Support', # this is optional
      phone: '+16501234567' # this is the channel phone number
    },
    from: {
      name: 'Customer name',
      phone: '+15105559999' # this is the customer's phone number
    },
    body: 'This is the SMS message body',
    attachments: [
      'https://www.example.com/image1.png'
    ]
  }.to_json

  digest = OpenSSL::Digest.new('sha256')
  calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, SHARED_SECRET, data)).strip

  req.headers['X-Reamaze-Hmac-SHA256'] = calculated_hmac
  req.headers['Content-Type'] = 'application/json'
  req.body = body
end
Creating the SMS in Re:amaze

When an SMS is received by the SMS number, you'll need to send a POST request to https://www.reamaze.io/incoming/sms with the following data:

{
  id: 'sms-message-id', # required - this is the id of the message
  to: {
    name: 'Support', # optional - name of the support channel or brand
    phone: '+16501234567' # required - this is the channel phone number
  },
  from: {
    name: 'Customer name', # optional - name of the sender
    phone: '+15105559999' # required - phone number of the sender
  },
  body: 'This is the SMS message body', # required - sms message body
  attachments: [ # optional array of attachment urls
    'https://www.example.com/image1.png'
  ],
  created_at: '2019-08-06T23:21:15+0000' # optional - iso8601 datetime of when SMS was created
}

Re:amaze will then respond with a status code of 2xx if the request was successful. An status code of 5xx is a temporary failure and the request should be retried. A status code of 4xx usually means that the request does not parse and should not be retried before fixing the request parameters.

Receiving SMS from Re:amaze

Similarly, when a staff user responds to a customer SMS, a POST request is sent to the webhook url  defined in the channel settings with the following data:

{
  to: {
    name: 'Support', # optional - name of the support channel or brand
    phone: '+16501234567' # required - this is the channel phone number
  },
  from: {
    name: 'Customer name', # optional - name of the sender
    phone: '+15105559999' # required - phone number of the sender
  },
  body: 'This is the SMS message body', # required - sms message body
  attachments: [ # optional array of attachment urls
    'https://www.example.com/image1.png'
  ],
  created_at: '2019-08-06T23:21:15+0000' # optional - iso8601 datetime of when SMS was created
}

This request is sent synchronously when a staff submits a reply to an SMS conversation, and you should return a status code of 200 or 201 if and only if the SMS was actually sent on your end.

Help / Questions?

For questions regarding our custom channel integrations, contact us at support@reamaze.com or talk to us via our chat widget at https://www.reamaze.com