1. Run git clone and create and set your API credentials

  1. Open a shell session.
  2. If needed, create a directory where you want to deploy SMS Proxy.
  3. Change to the directory where you want to install SMS Proxy, and run the following:
  4. git clone https://github.com/flowroute/sms-proxy.git
                    

    The git clone command clones the sms-proxy repository as a sub-directory within the parent folder.

  5. Switch to ./sms-proxy/sms_proxy.
  6. Using your preferred text editor, open settings.py. In this file, set your API credentials by replacing the FLOWROUTE_SECRET_KEY and FLOWROUTE_ACCESS_KEY with your own:
    FLOWROUTE_SECRET_KEY = os.environ.get('FLOWROUTE_SECRET_KEY', None)
    FLOWROUTE_ACCESS_KEY = os.environ.get('FLOWROUTE_ACCESS_KEY', None)
    
                    

    You can also configure variables here that are used by the application, or alternatively these settings may be passed in as environment variables when you deploy the service. See Configure SMS Proxy for more information.

  7. Deploy the SMS Proxy service.

2. Deploy the microservice

Deploying the service can be done by either building and running a Docker container as specified by the provided Dockerfile, or by running the application locally with Flask's built-in web server. You can first run the application in test mode before running in production mode.

DEBUG mode

During development, DEBUG_MODE should be set to Truein settings.py in order to use the auto-generated test database. Testing can be performed on this database, which drops data in the tables each time the test module is run. Once the development cycle is over, set DEBUG_MODE to False in order to use the production database. Tests cannot be run when the production database is active.

To run the application using Docker:

  1. Run the following at the project's top level to build the service:
  2.  docker build -t sms_proxy:0.0.1 .
    
                        

    -t tags the image, allowing you to reference it by name instead of by image ID.

  3. Next, run the following:
  4.  docker run -p 8000:8000 sms_proxy:0.0.1
    
                        
    -p binds the container port to the Docker host port. When using a virtualization layer, such as Docker-machine, the API should now be exposed on that host — for example, http://192.168.99.100:8000.

    By default, the run command spawns four Gunicorn workers listening on port 8000. To modify the run command, edit the settings in the Docker entry file (Dockerfile) located in the project root.

    To run the application locally:

    1. From your sms-proxy directory, run:
    2. pip install -r requirements.txt
                              
    3. Run the following to install the service dependencies at the root level of the project:
    4. pip install .
                              
    5. Finally, run:
    6. python -m sms_proxy.api
                              

      The service is set up at the root level.

    Flask Documentation

    See the Flask documentation for more information about the micro web framework.

    3. Configure SMS Proxy

    With the service now deployed, configure message settings by customizing settings.py. This allows you to customize session parameters, such as start and end messages, or organization name.

    To configure message settings:

    1. In the ./sms-proxy/sms_proxy directory, open settings.py using a text editor.
    2. Modify any of the following values as needed:
    ORG_NAME = os.environ.get('ORG_NAME', 'Your Org Name')
    SESSION_START_MSG = os.environ.get('SESSION_START_MSG', 'Your new session has started, send a message!')
    SESSION_END_MSG = os.environ.get('SESSION_END_MSG', 'This session has ended, talk to you again soon!')
    NO_SESSION_MSG = os.environ.get('NO_SESSION_MSG', 'An active session was not found. Please contact support@yourorg.com')
    
                            

    The following fields can be modified in settings.py:

    Variable Required Data Type Description
    ORG_NAME True string Sets your organization's name for use in system-generated SMS messages. If the ORG_NAME variable is not changed, Your Org Name is used as the default.
    SESSION_START_MSG True string The message that is sent to both participants when their session has been created.
    SESSION_END_MSG True string The message sent to both participants when a session has been terminated using the DELETE method. This message is not sent for an expired session.
    NO_SESSION_MSG True string The message sent to a user who sends a message to a virtual phone number that
    1. is assigned to a session to which the user is not a participant of, or
    2. is not assigned to any active session.

    4. Test it!

    Docker commands

    Depending on your Docker system configuration, you may be required to preface each docker command with sudo. Read more about it here.

    In a test environment, invoke the docker run command with the test argument to run tests and see results. To change the docker run command options, modify the test, coverage, or serve options in the entry script located in the top-level sms-proxy directory.

    Docker Entry Points

    To learn more about Docker entry points, see Dockerfile Best Practices.

    Run the following:

     docker run -p 8000:8000 sms_proxy:0.0.1 test
                            

    A py.test command is invoked from within the container. When running coverage, a cov-report directory is created that contains an index.html file detailing test coverage results.

    5. Add a virtual phone number (TN) and start a session

    Once the application is up and running, you can begin adding one or more virtual phone numbers and creating sessions. SMS Proxy has a 1-to-1 mapping of number to session; the more numbers you add to your pool, the more simultaneous sessions you can create.

    See Exposed HTTP Resources for more information.

    Add a virtual phone number (POST)

    To add a virtual phone number to your pool, use a curl POST command, as shown in the following examples:

    cURL using Docker
    curl -H "Content-Type: application/json" -X POST -d \ 
    '{"value":"1XXXXXXXXXX"}' \
    https://<DockerHost>:<port>/tn
                            
    cURL using SimpleHTTPServer
    curl -H "Content-Type: application/json" -X POST -d \ 
    '{"value":"1XXXXXXXXXX"}' \
    http://0.0.0.0:8000/tn
                            

    Example Response

    {
    "message": "Successfully added TN to pool", 
    "value": "12061231234"
    }
    
                            

    The statement takes the following arguments:

    Key:Argument Required Data Type Constraint
    value: virtual_tn True integer The 11-digit telephone number used during a session. Participants send and receive their messages from this phone number when it is in use during a session. Virtual phone numbers must be phone numbers that you have purchased from Flowroute.
    https://: True string The HTTP or HTTPS endpoint where the service is located. The URL path is the IP address of the service. When using a virtualization layer, such as Docker-machine, the API should be exposed on that host. e.g. http://192.168.99.100:8000.

    Important

    When using the POST method with JSON, you must also include the complete "Content-Type:application/json" header.

    Start a session (POST)

    To start a session, use a curl POST command, as shown in the following example:

    cURL
    curl -H "Content-Type: application/json" -X POST -d \
    '{"participant_a":"1XXXXXXXXXX", "participant_b":"1XXXXXXXXXX", "expiry_window": 10}' \
    https://<DockerHost>:<port>/session
                            
    The statement takes the following arguments:
    Key:Argument Required Data Type Constraint
    participant_a:phone_number True string The 11-digit telephone number of the first participant in a session, in E.164 1XXXXXXXXXX format.
    participant_b:phone_number True string The 11-digit telephone number of the second participant in a session, in E.164 1XXXXXXXXXX format.
    expiry_window False integer The number of minutes the session should be active. Any messages received after this time will end the session. Participants will receive a system-generated SMS message indicating that the session has ended. Subsequent messages will trigger a NO_SESSION_MSG from settings.py.
    https://: True string The HTTP or HTTPS endpoint where the service is located. The URL path is the IP address of the service. When using a virtualization layer, such as Docker-machine, the API should be exposed on that host. e.g. http://192.168.99.100:8000.

    The following then occurs:

    1. A virtual phone number is selected at random from the pool. If no virtual phone numbers are available, the following message is returned:
    2. {"message": "Could not create session -- No virtual TNs available"}
                                  
    3. A session is created between the two participants using an available virtual phone number from the pool.
    4. The proxy will relay messages sent to the virtual phone number for the number of minutes specified for the expiry_window if set; otherwise, the session will persist indefinitely or until the session is ended through a DELETE request against the session endpoint.

    6. End a session

    Run the following DELETE statement to end a session:

    cURL
    curl -H "Content-Type: application/json" -X DELETE -d '{"session_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}' https://&amp;lt;DockerHost&amp;gt;<:port>.com/session 
                        

    The statement takes the following arguments:

    Key:Argument Required Data Type Constraint
    session_id True string A 32-character alphanumeric session identifier.
    https://&amp;lt;DockerHost&amp;gt;:&amp;lt;port&amp;gt; True string The HTTP or HTTPS endpoint where the service is located. The URL path is the IP address of the service. When using a virtualization layer, such as Docker-machine, the API should be exposed on that host. e.g. http://192.168.99.100:8000.

    Exposed HTTP Resources

    The following URL resources are supported for the endpoints. The following examples show POST, GET, and DELETE HTTP methods for the applicable URL resource.

    See Add a virtual phone number and start a session for descriptions of the fields passed in the request.

    • /
      • POST handles the incoming messages received from Flowroute. / is the endpoint that sets the callback URL to the URL set in your Flowroute Manager API settings.
    • /tn
      • POST adds a phone number to your pool of virtual phone numbers.

      • Example POST Request
        curl -H "Content-Type: application/json" \
        -X POST -d '{"value":"12062992129"}' \
         https://yourdomain.com/tn 
                                    
        Example Response
        {
        "message": "successfully added TN to pool", 
        "value": "12062992129"
        }
                                    
      • GET retrieves your entire virtual phone number pool.
      • Example GET Request
        curl -H "Content-Type: application/json" \
        -X GET https://yourdomain.com/tn
                                    
        Example response
        {
        "available": 0, 
        "in_use": 1, 
        "pool_size": 1, 
        "virtual_tns": 
        	[{"session_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
        	"value": "12062992129"}]
        }
                                    

        The following table describes the fields returned in the response:

        Key Description
        available The number of unreserved virtual phone numbers (TNs).
        in_use The number of pool sessions currently being used.
        pool_size The sum of both reserved and unreserved phone numbers (TNs).
        value The pool identifier.
      • DELETE removes a phone number (TN) from your pool of virtual TNs.
      Example DELETE Request
      curl -H "Content-Type: application/json" -X DELETE -d \
      '{"value":"12062992129"}' \
      https://yourdomain.com/tn 
                                  
      Example Response
      {
        "message": "successfully removed TN from pool", 
        "value": "12062992129"
      }
                                  
    • /session
      • POST starts a new session between participant_a and participant_b. An optional expiration time, in minutes, can be passed indicating when a session should expire. If not passed, the session will not end until a DELETE request is sent. The following examples shows a POST request setting an expiration time of 10 (ten) minutes:
      • Example POST Request
        curl -H "Content-Type: application/json" -X POST \
        -d '{"participant_a":"1XXXXXXXXXX", 
        "participant_b":"1XXXXXXXXXX", 
        "expiry_window": 10}' 
        https://yourdomain.com/session
        
                                

        A response message is returned indicating a successful POST for the expiration time:

        Example Response
        {
          "virtual_tn": "1XXXXXXXXXX", 
          "session_id": "366910827c8e4a6593943a28e4931668", 
          "expiry_date": "2016-05-19 22:19:58", 
          "participant_b": "12065551213", 
          "message": "created session", 
          "participant_a": "12065551212"
        }
                                
      • GET lists all in-progress sessions.
      • Example GET
        curl -H "Content-Type: application/json" -X GET https://yourdomain.com/session
                                
        Example Response
        {
        "total_sessions": 1, 
            "sessions": [
                {
                    "virtual_tn": "1XXXXXXXXXX", 
                    "expiry_date": "2016-05-19 22:19:58", 
                    "participant_b": "12065551212", 
                    "date_created": "2016-05-19 22:09:58", 
                    "participant_a": "12065551213", 
                    "id": "366910827c8e4a6593943a28e4931668"
                }
            ]
        }
                                
      • DELETE ends the specified session.
      • Example DELETE Request
         curl -H "Content-Type: application/json" \
        -X DELETE -d \
        '{"session_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}' \ 
        https://MyDockerHostIP/session
                                
        Example Response
        {
        "message": "successfully ended session", 
        "session_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        }