diff --git a/README.md b/README.md index 4cdf529..c1ea940 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Flowroute SDK for Python (v3) ===================== -The Flowroute SDK v3 for Python provides methods for interacting with [Numbers v2](https://developer.flowroute.com/api/numbers/v2.0/ and [Messages v2.1](https://developer.flowroute.com/api/messages/v2.1/) of the [Flowroute](https://www.flowroute.com) API. +The Flowroute SDK for Python (v3) provides methods for interacting with [Numbers v2](https://developer.flowroute.com/api/numbers/v2.0/) and [Messages v2.1](https://developer.flowroute.com/api/messages/v2.1/) of the [Flowroute](https://www.flowroute.com) API. **Topics** @@ -41,20 +41,20 @@ Usage ------------ In Flowroute's approach to building SDK v3 for Python, HTTP requests are handled by controllers named after the API resources they represent: **Numbers**, **Routes**, and **Messages**. These controllers contain the methods used to perform messaging, number management, and route management within the Python SDK. -### Controllers +## Controllers -#### NumbersController +### NumbersController Contains all of the methods necessary to search through Flowroute's phone number inventory, purchase a phone number, and review details of your account phone numbers. * [list\_available\_area\_codes()](#list_available_area_codes) \- Returns a list of all Numbering Plan Area (NPA) codes containing purchasable phone numbers. All request parameters are optional. If you don't specify a limit, results are limited to the first 10 items. * [list\_available\_exchange\_codes()](#list_available_exchange_codes) \- Returns a list of all Central Office (exchange) codes containing purchasable phone numbers. All request parameters are optional. * [search\_for\_purchasable\_phone\_numbers()](#search_for_purchasable_phone_numbers) \- Searches for purchasable phone numbers by state or rate center, or by your specified search value. -* [purchase\_a\_phone\_number(number\_id)](#purchase_a_phone_numbernumber_id) \- Lets you purchase a phone number from available Flowroute inventory. +* [purchase\_a\_phone\_number(purchasable\_number)](#purchase_a_phone_numbernumber_id) \- Lets you purchase a phone number from available Flowroute inventory. * [list\_account\_phone\_numbers()](#list_account_phone_numbers) \- Returns a list of all phone numbers currently on your Flowroute account. -* [list\_phone\_number\_details(numberid)](#list_phone_number_detailsnumber_id) \- Returns details on a specific phone number associated with your account, including primary voice route, and failover voice route if previously configured. +* [list\_phone\_number\_details(number\_id)](#list_phone_number_detailsnumber_id) \- Returns details on a specific phone number associated with your account, including primary voice route, and failover voice route if previously configured. -#### RoutesController +### RoutesController Contains the methods required to create new inbound routes, view all of your account routes, and update primary and failover voice routes for your phone numbers. @@ -63,7 +63,7 @@ Contains the methods required to create new inbound routes, view all of your acc * [update\_primary\_voice\_route(number\_id, route\_body)](#update_primary_voice_routenumber_id-route_body) \- Updates the primary voice route for a phone number. You must create the route first via the `create_an_inbound_route(routebody)` method. * [update\_failover\_voice\_route(number\_id, route\_body)](#update_failover_voice_routenumber_id-route_body) \- Updates the failover voice route for a phone number. You must create the route first via the `create_an_inbound_route(routebody)` method. -#### MessagesController +### MessagesController Contains the methods required to send an MMS or SMS, and review a specific Message Detail Record (MDR) or a set of messages. @@ -77,6 +77,9 @@ The following shows an example of a single Python file that imports the Flowrout import pprint import os import json +import random +import string +import requests from flowroutenumbersandmessaging.flowroutenumbersandmessaging_client import FlowroutenumbersandmessagingClient ``` #### Credentials @@ -84,9 +87,10 @@ from flowroutenumbersandmessaging.flowroutenumbersandmessaging_client import Flo In **demo.py**, replace `basic_auth_user_name` with your API Access Key and `basic_auth_password` with your API Secret Key from the [Flowroute Manager](https://manage.flowroute.com/accounts/preferences/api/). Note that in our example, we are accessing your Flowroute credentials as environment variables. To learn more about setting environment variables, see [How To Read and Set Environmental and Shell Variables](https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps). ```python -# Set up your api credentials +# Set up your api credentials and test mobile number for outbound SMS or MMS basic_auth_user_name = os.environ.get('FR_ACCESS_KEY') basic_auth_password = os.environ.get('FR_SECRET_KEY') +mobile_number = "YOUR_MOBILE_NUMBER" ``` #### Instantiate API Client and Controllers Next, instantiate the API Client and its controllers. @@ -98,7 +102,8 @@ numbers_controller = client.numbers routes_controller = client.routes messages_controller = client.messages ``` -#### Methods +## Methods +The following section will demonstrate the capabilities of Numbers v2 and Messages v2.1 that are wrapped in our Python library. Note that the example responses have been formatted using Mac's `pbpaste` and `jq`. To learn more, see [Quickly Tidy Up JSON from the Command Line](http://onebigfunction.com/vim/2015/02/02/quickly-tidying-up-json-from-the-command-line-and-vim/). ### Number Management @@ -119,6 +124,9 @@ pprint.pprint(result) ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains an array of area code objects in JSON format. + ``` { "data": [ @@ -166,6 +174,9 @@ result = numbers_controller.list_available_exchange_codes(limit, offset, max_set pprint.pprint(result) ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains an array of exchange objects in JSON format. + ``` { "data": [ @@ -216,6 +227,9 @@ result = numbers_controller.search_for_purchasable_phone_numbers(starts_with, co ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains an array of phone number objects in JSON format. + ``` { "data": [ @@ -272,20 +286,20 @@ result = numbers_controller.search_for_purchasable_phone_numbers(starts_with, co } ``` -#### purchase\_a\_phone\_number(number\_id) - -The method is used to purchase a telephone number from Flowroute's inventory and accepts the phone number `id` as a parameter which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/purchase-a-phone-number/). +#### purchase\_a\_phone\_number(purchasable\_number) +The method is used to purchase a telephone number from Flowroute's inventory and accepts the phone number `id` as a parameter which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/purchase-a-phone-number/). In the following example, we assign the `id` of the first phone number in the resulting JSON array as the phone number to be purchased. Note that this function call is currently commented out. Uncomment to test the `purchase_a_phone_number` method. ##### Example Request ```python print("--Purchase a Phone Number") -numberid = result['data'][0]['id'] -result = numbers_controller.purchase_a_phone_number(numberid) +purchasable_number = result['data'][0]['id'] +result = numbers_controller.purchase_a_phone_number(purchasable_number) ``` -In the example above, we have assigned the `id` of the first phone number in the resulting JSON array as the phone number to be purchased. - #### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains a phone number object in JSON format. + ``` { "data": { @@ -358,6 +372,9 @@ pprint.pprint(result) ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains an array of phone number objects in JSON format. + ``` { "data": [ @@ -400,16 +417,20 @@ pprint.pprint(result) #### list\_phone\_number\_details(number\_id) -The method accepts the `number_id` as a parameter which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/list-phone-number-details/). In the following example, we request the details of our newly purchased phone number above. +The method accepts the `number_id` as a parameter which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/list-phone-number-details/). In the following example, we request the details of the first phone number returned after calling the `list_account_phone_numbers` method. ##### Example Request ```python print("--List Phone Number Details") -result = numbers_controller.list_phone_number_details(numberid) +number_id = result['data'][0]['id'] +result = numbers_controller.list_phone_number_details(number_id) pprint.pprint(result) ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains a phone number object in JSON format. + ``` { "included": [ @@ -469,35 +490,44 @@ pprint.pprint(result) Flowroute SDK version 3 for Python allows you to make HTTP requests to the `routes` resource of Flowroute API v2: `https://api.flowroute.com/v2/routes` #### create\_an\_inbound\_route(route\_body) -WIP -The method accepts the route object in JSON format as a parameter which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/create-an-inbound-route/). +The method accepts the route object in JSON format as a parameter which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/create-an-inbound-route/). In the following example, we define a function to generate a six-character random string for our subdomain which we later concatenate with our example domain and assign as our `host` value. ##### Example Request ```python print ("---Create an Inbound Route") +# Function to generate six-charac random string +def id_generator(size=6, chars=string.ascii_lowercase + string.digits): + return ''.join(random.choice(chars) for _ in range(size)) +new_route = id_generator() + '.sonsofodin.com' +alias = "new route" +for i in range(10): alias += str(i) +print new_route request_body = '{ \ "data": { \ "type": "route", \ "attributes": { \ - "route_type": "number", \ - "value": "' + str(number_id) +'", \ - "alias": "new_route_id" \ + "route_type": "host", \ + "value": "' + new_route +'", \ + "alias": "' + alias + '" \ } \ } \ }' result = routes_controller.create_an_inbound_route(request_body) -pprint.pprint(result) +print result ``` ##### Example Response + +On success, the HTTP status code in the response header is `201 Created` and the response body contains a route object in JSON format. + ``` { "data": { "attributes": { - "alias": "new_route_id", - "route_type": "number", - "value": "12011231234" + "alias": "new route", + "route_type": "host", + "value": "il775u.sonsofodin.com" }, "id": "98396", "links": { @@ -517,11 +547,15 @@ The method accepts `limit` and `offset` as parameters which you can learn more a ##### Example Request ```python print ("---List Inbound Routes") -result = routes_controller.list_inbound_routes() +limit = 3 +result = routes_controller.list_inbound_routes(limit) pprint.pprint(result) ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains an array of route objects in JSON format. + ``` { "data": [ @@ -558,66 +592,198 @@ pprint.pprint(result) ``` #### update\_primary\_voice\_route(number\_id, route\_body) -WIP -The method accepts a phone number `id` and a route record object in JSON format as parameters which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/update-number-primary-voice-route/). +The method accepts a phone number `id` and a route record object in JSON format as parameters which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/update-number-primary-voice-route/). In the following example, we extract the second route in our `list_inbound_routes` search result and assign it as the primary voice route for our previously declared `number_id`. ##### Example Request ```python -print ("---Update Primary Voice Route for a Phone Number") +prirouteid = result['data'][1]['id'] +request_body = '{ \ + "data": { \ + "type": "route", \ + "id": "' + str(prirouteid) +'" \ + } \ +}' + +print ("---Update Primary Voice Route") +result = routes_controller.update_primary_voice_route(number_id, request_body) +if result is None: + print "204: No Content" +else: + print result ``` ##### Example Response -`204 NO CONTENT` -On success, the HTTP status code in the response header is `204 NO CONTENT` which means that the server successfully processed the request and is not returning any content. +On success, the HTTP status code in the response header is `204 No Content` which means that the server successfully processed the request and is not returning any content. + +`204: No Content` + #### update\_failover\_voice\_route(number\_id, route\_body) -WIP -The method accepts a phone number `id` and a route record object in JSON format as parameters which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/update-number-failover-voice-route/). +The method accepts a phone number `id` and a route record object in JSON format as parameters which you can learn more about in the [API reference](https://developer.flowroute.com/api/numbers/v2.0/update-number-failover-voice-route/). In the following example, we extract the third and last route in our `list_inbound_routes` search result and assign it as the failover voice route for our previously declared `number_id`. ##### Example Request ```python -print ("---Update Failover Voice Route for a Phone Number") +secrouteid = result['data'][2]['id'] +request_body = '{ \ + "data": { \ + "type": "route", \ + "id": "' + str(secrouteid) +'" \ + } \ +}' + +print ("---Update Failover Voice Route") +result = routes_controller.update_failover_voice_route(number_id, request_body) +if result is None: + print "204: No Content" +else: + print result ``` ##### Example Response -`204 NO CONTENT` +`204: No Content` -On success, the HTTP status code in the response header is `204 NO CONTENT` which means that the server successfully processed the request and is not returning any content. +On success, the HTTP status code in the response header is `204 No Content` which means that the server successfully processed the request and is not returning any content. ### Messaging Flowroute SDK version 3 for Python allows you to make HTTP requests to the `messages` resource of Flowroute API v2.1: `https://api.flowroute.com/v2.1/messages` #### send\_a\_message(message\_body) -WIP -The method accepts a message object in JSON format as a parameter which you can learn more about in the API References for [MMS](https://developer.flowroute.com/api/messages/v2.1/send-an-mms/) and [SMS](https://developer.flowroute.com/api/messages/v2.1/send-an-sms/). +The method accepts a message object in JSON format as a parameter which you can learn more about in the API References for [MMS](https://developer.flowroute.com/api/messages/v2.1/send-an-mms/) and [SMS](https://developer.flowroute.com/api/messages/v2.1/send-an-sms/). In the following example, we are sending an MMS with a `gif` attachment from the previously declared `number_id` to your mobile number. ##### Example Request ```python -print ("---Send a Message") +request_body = '{ \ + "data": { \ + "type": "message", \ + "attributes": { \ + "to": "' + str(mobile_number) + '", \ + "from": "' + str(number_id) + '", \ + "body": "hello there", \ + "is_mms": "true", \ + "media_urls": ["http://s3.amazonaws.com/barkpost-assets/50+GIFs/37.gif"] \ + } \ + } \ +}' + +print ("---Send A Message") +result = messages_controller.send_a_message(request_body) +pprint.pprint(result) ``` ##### Example Response -`202 ACCEPTED` On success, the HTTP status code in the response header is `202 Accepted` and the response body contains the message record ID with `mdr2` prefix. +``` +{ + "data": { + "links": { + "self": "https://api.flowroute.com/v2.1/messages/mdr2-39cadeace66e11e7aff806cd7f24ba2d" + }, + "type": "message", + "id": "mdr2-39cadeace66e11e7aff806cd7f24ba2d" + } +} +``` + + +#### look\_up\_a\_set\_of\_messages(start\_date) + +The method accepts `start_date`, `end_date`, `limit`, and `offset` as parameters which you can learn more about in the [API Reference](https://developer.flowroute.com/api/messages/v2.1/look-up-set-of-messages/). + +##### Example Request +```python +print ("---Look Up A Set Of Messages") +start_date = "2017-12-01" +end_date = "2018-01-08" +limit = 2 +result = messages_controller.look_up_a_set_of_messages(start_date, end_date, limit) +pprint.pprint(result) +``` + +##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains an array of message objects in JSON format. + +``` +{ + "data": [ + { + "attributes": { + "body": "Hello are you there? ", + "status": "delivered", + "direction": "inbound", + "amount_nanodollars": 4000000, + "to": "12012673227", + "message_encoding": 0, + "timestamp": "2017-12-22T01:52:39.39Z", + "delivery_receipts": [], + "amount_display": "$0.0040", + "from": "12061231234", + "is_mms": false, + "message_type": "longcode" + }, + "type": "message", + "id": "mdr2-ca82be46e6ba11e79d08862d092cf73d" + }, + { + "attributes": { + "body": "test sms on v2", + "status": "message buffered", + "direction": "outbound", + "amount_nanodollars": 4000000, + "to": "12061232634", + "message_encoding": 0, + "timestamp": "2017-12-21T16:44:34.93Z", + "delivery_receipts": [ + { + "status": "message buffered", + "status_code": 1003, + "status_code_description": "Message accepted by Carrier", + "timestamp": "2017-12-21T16:44:35.00Z", + "level": 2 + }, + { + "status": "smsc submit", + "status_code": null, + "status_code_description": "Message has been sent", + "timestamp": "2017-12-21T16:44:35.00Z", + "level": 1 + } + ], + "amount_display": "$0.0040", + "from": "12012673227", + "is_mms": false, + "message_type": "longcode" + }, + "type": "message", + "id": "mdr2-39cadeace66e11e7aff806cd7f24ba2d" + } + ], + "links": { + "next": "https://api.flowroute.com/v2.1/messages?limit=2&start_date=2017-12-01T00%3A00%3A00%2B00%3A00&end_date=2018-01-08T00%3A00%3A00%2B00%3A00&offset=2" + } +} +``` + #### look\_up\_a\_message\_detail\_record(message\_id) -The method accepts a message `id` in MDR2 format as a parameter which you can learn more about in the [API Reference](https://developer.flowroute.com/api/messages/v2.1/look-up-a-message-detail-record/). +The method accepts a message `id` in MDR2 format as a parameter which you can learn more about in the [API Reference](https://developer.flowroute.com/api/messages/v2.1/look-up-a-message-detail-record/). In the following example, we retrieve the details of the first message in our `look_up_a_set_of_messages` search result. ##### Example Request ```python -print ("---Look Up a Message Detail Record") -message_id = "mdr2-ca82be46e6ba11e79d08862d092cf73d" +message_id = result['data'][0]['id'] result = messages_controller.look_up_a_message_detail_record(message_id) pprint.pprint(result) ``` ##### Example Response + +On success, the HTTP status code in the response header is `200 OK` and the response body contains the message object for our specified message `id`. ``` { "data": { @@ -640,33 +806,12 @@ pprint.pprint(result) } } ``` - -#### look\_up\_a\_set\_of\_messages(start\_date) -WIP -The method accepts `start_date`, `end_date`, `limit`, and `offset` as a parameters which you can learn more about in the [API Reference](https://developer.flowroute.com/api/messages/v2.1/look-up-set-of-messages/). - -##### Example Request -```python -print ("---Look Up a Set of Messages") -``` - -##### Example Response -`202 ACCEPTED` -On success, the HTTP status code in the response header is `202 Accepted` and the response body contains the message record ID with `mdr2` prefix. #### Errors -In cases of method errors, the API Controller returns an error object with the same fields as our [API's error response](https://developer.flowroute.com/api/errors). +In cases of method errors, the Python library raises an exception which includes the HTTP Response code, an error message, and the HTTP body that was received in the request. ##### Example Error ``` -{ - "errors": [ - { - "detail": "Error fetching media: File at \"https://s3-us-west-2.amazonaws.com/testing/1503617641_12067392634\" is over 767840 byte limit.", - "id": "8f20a349-ebc0-4246-81ae-b4e7caef324c", - "status": 422 - } - ] -} +raise ErrorException('403 Forbidden – The server understood the request but refuses to authorize it.', _context) ```