Custom SMS Channel Integration

Re:amaze allows you to connect third-party SMS providers that are not natively supported by linking them as custom SMS channels. This gives you the flexibility to build your own SMS integrations within Re:amaze tailored to your specific needs.

How it works

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

Authentication

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

Code examples for generating the SHA256 HMAC:

// PHP:
$data = '{"id":"1","body":"hello"}';
$shared_secret = 'your_shared_secret';
$calculated_hmac = base64_encode(hash_hmac('sha256', $data, $shared_secret, true));

// RUBY:
require 'base64'
require 'openssl'
SHARED_SECRET = 'your_shared_secret'
data = '{"id":"1","body":"hello"}'
calculated_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', SHARED_SECRET, data))

Ruby Sinatra example for verifying a request 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

Ruby Sinatra example for verifying a request from Re:amaze:

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", 
    direction: "outbound", # optional, defaults to 'inbound'
    to: {
      name: 'Support', # this is optional
      phone: '+16501234567' # if outbound direction, this is the customer number, otherwise this is the channel phone number
    },
    from: {
      name: 'Customer name',
      phone: '+15105559999' # if outbound direction, this is the channel phone number, otherwise this is the customer phone number
    },
    body: 'This is the SMS message body',
    attachments: [ # optional - list of attachment urls
      'https://www.example.com/image1.png'
    ],
    thread_id: 'sms-conversation-id-123',  # optional, but highly recommended - unique id identify the entire sms conversation. SMS messages with the same thread_id will be grouped in the same conversation inside Re:amaze. When left blank, the SMS will be attributed to the customer's most recent SMS conversation in Re:amaze that happened within the past hour.
    created_at: '2019-08-06T23:21:15+0000', # optional - iso8601 datetime of when SMS was created
    assignee: { # optional - when provided and if the email matches a staff email, the related conversation will be assigned to that staff user. Absence of this parameter will not unassign the conversation.
      email: "staffemail@example.com"
    }
  }.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

Send an inbound SMS to Re:amaze

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

{
  "id": "sms-message-id",
  "direction": "inbound",
  "to": {
    "name": "Support",
    "phone": "+16501234567"
  },
  "from": {
    "name": "Customer name",
    "phone": "+15105559999"
  },
  "body": "This is the SMS message body",
  "attachments": [
    "https://www.example.com/image1.png"
  ],
  "thread_id": "sms-conversation-id-123",
  "created_at": "2019-08-06T23:21:15+0000",
  "assignee": {
    email: "staffemail@example.com"
  }
}

Re:amaze will respond with a status code of 2xx if the request was successful. A status code of 5xx indicates a temporary failure and the request should be retried. A status code of 4xx typically means the request could not be parsed and should not be retried until the request parameters are corrected.

Receive an outbound SMS from Re:amaze

When a staff member responds to a customer SMS, Re:amaze sends a POST request to the webhook url defined in your channel settings with the following data:

{
  "to": {
    "name": "Support",
    "phone": "+16501234567"
  },
  "from": {
    "name": "Customer name",
    "phone": "+15105559999"
  },
  "body": "This is the SMS message body",
  "conversation": {
    "slug": "thread-slug",
  },
  "attachments": [
    "https://www.example.com/image1.png"
  ],
  "created_at": "2019-08-06T23:21:15+0000",
  "thread_id": "sms-conversation-id-123"
}

This request is sent synchronously when a staff member submits a reply to an SMS conversation. Return a status code of 200 or 201 only if the SMS was successfully sent on your end.

This request payload contains additional conversation meta data which contains the slug attribute to identify the conversation on the Re:amaze side. This identifier can be used as a threading hint or to retrieve additional information about the conversation via the Re:amaze API.

Note: This webhook is not triggered when you send a message to Re:amaze with direction = "outbound".

Get help

For questions about custom channel integrations, contact support@reamaze.com or reach out via the chat widget at reamaze.com.

Not finding what you're looking for? Contact Us Directly