From 19d2886478c8339450476c488379f660505137c3 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 8 Jan 2018 18:22:45 -0800 Subject: [PATCH 01/17] changed create route value to be a null route of 8.8.8.8 --- demo.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/demo.py b/demo.py index b973358..45f1fd3 100755 --- a/demo.py +++ b/demo.py @@ -9,8 +9,11 @@ from flowroutenumbersandmessaging.models.new_route import NewRoute print("Number/Route Management v2 & Messaging v2.1 Demo") # Set up your api credentials -basic_auth_user_name = os.environ.get('FR_ACCESS_KEY') -basic_auth_password = os.environ.get('FR_SECRET_KEY') +#basic_auth_user_name = os.environ.get('FR_ACCESS_KEY') +#basic_auth_password = os.environ.get('FR_SECRET_KEY') +basic_auth_user_name = 'FR_ACCESS_KEY' +basic_auth_password = 'FR_SECRET_KEY' + # Instantiate API client and create controllers for Numbers, Messages, and Routes client = FlowroutenumbersandmessagingClient(basic_auth_user_name, basic_auth_password) @@ -65,18 +68,20 @@ pprint.pprint(result) print ("---Create an Inbound Route") +host_address = '8.8.8.8' request_body = '{ \ "data": { \ "type": "route", \ "attributes": { \ "route_type": "host", \ - "value": "' + str(number_id) +'", \ + "value": "' + str(host_address) +'", \ "alias": "new_route_id" \ } \ } \ }' result = routes_controller.create_an_inbound_route(request_body) +print result pprint.pprint(result) print ("---List Inbound Routes") From 0a2ae1807fa1afc6c69bf2f81fe6df8337d2c7a0 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Mon, 8 Jan 2018 22:00:40 -0800 Subject: [PATCH 02/17] Remove merge conflicts --- demo.py | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/demo.py b/demo.py index cc34066..b4fd791 100755 --- a/demo.py +++ b/demo.py @@ -60,30 +60,10 @@ offset = None result = numbers_controller.list_account_phone_numbers(starts_with, ends_with, contains, limit, offset) pprint.pprint(result) -<<<<<<< HEAD + print("--List Phone Number Details") number_id = result['data'][0]['id'] result = numbers_controller.list_phone_number_details(number_id) -======= - -print ("---Create an Inbound Route") -host_address = '8.8.8.8' -request_body = '{ \ - "data": { \ - "type": "route", \ - "attributes": { \ - "route_type": "host", \ - "value": "' + str(host_address) +'", \ - "alias": "new_route_id" \ - } \ - } \ -}' - -result = routes_controller.create_an_inbound_route(request_body) -print result ->>>>>>> 890bb1052f22d46307c7ca823c95e56d2ed46ee5 -pprint.pprint(result) - print ("---List Inbound Routes") limit = 3 @@ -136,7 +116,7 @@ request_body = '{ \ print ("---Send A Message") #result = messages_controller.send_a_message(request_body) -pprint.pprint(result) +#pprint.pprint(result) print ("---Look Up A Set Of Messages") start_date = '2017-12-01' @@ -167,4 +147,4 @@ request_body = '{ \ } \ }' result = routes_controller.create_an_inbound_route(request_body) -print ("---New Route Created") +print "New Route Created" From 0fbff176917cba32f41faba80bdc1db9280c617c Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Tue, 9 Jan 2018 12:41:51 -0800 Subject: [PATCH 03/17] Final touches to demo, update routes_controller header info --- demo.py | 16 ++++++++++------ .../controllers/routes_controller.py | 6 ++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/demo.py b/demo.py index b4fd791..50cce59 100755 --- a/demo.py +++ b/demo.py @@ -11,9 +11,11 @@ from flowroutenumbersandmessaging.models.new_route import NewRoute print("Number/Route Management v2 & Messaging v2.1 Demo") -# 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 create controllers for Numbers, Messages, and Routes client = FlowroutenumbersandmessagingClient(basic_auth_user_name, basic_auth_password) @@ -105,7 +107,7 @@ request_body = '{ \ "data": { \ "type": "message", \ "attributes": { \ - "to": "12067392634", \ + "to": "' + str(mobile_number) + '", \ "from": "' + str(number_id) + '", \ "body": "hello there", \ "is_mms": "true", \ @@ -119,8 +121,8 @@ print ("---Send A Message") #pprint.pprint(result) print ("---Look Up A Set Of Messages") -start_date = '2017-12-01' -end_date = '2018-01-08' +start_date = "2017-12-01" +end_date = "2018-01-08" result = messages_controller.look_up_a_set_of_messages(start_date, end_date) pprint.pprint(result) @@ -135,6 +137,8 @@ print ("---Create an Inbound Route") 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": { \ @@ -142,9 +146,9 @@ request_body = '{ \ "attributes": { \ "route_type": "host", \ "value": "' + new_route +'", \ - "alias": "test_route_id" \ + "alias": "' + alias + '" \ } \ } \ }' result = routes_controller.create_an_inbound_route(request_body) -print "New Route Created" +print result diff --git a/flowroutenumbersandmessaging/controllers/routes_controller.py b/flowroutenumbersandmessaging/controllers/routes_controller.py index 7acf3e5..660392d 100644 --- a/flowroutenumbersandmessaging/controllers/routes_controller.py +++ b/flowroutenumbersandmessaging/controllers/routes_controller.py @@ -30,7 +30,7 @@ class RoutesController(BaseController): body (NewRoute): The new inbound route to be created. Returns: - string: Response from the API. CREATED + mixed: Response from the API. CREATED Raises: APIException: When an error occurs while fetching the data from @@ -47,6 +47,7 @@ class RoutesController(BaseController): # Prepare headers _headers = { + 'accept': 'application/vnd.api+json', 'content-type': 'application/vnd.api+json; charset=utf-8' } @@ -54,11 +55,12 @@ class RoutesController(BaseController): _request = self.http_client.post(_query_url, headers=_headers, parameters=APIHelper.json_serialize(json.loads(body))) BasicAuth.apply(_request) _context = self.execute_request(_request) - print _context.response.status_code # Endpoint and global error handling using HTTP status codes. if _context.response.status_code == 401: raise ErrorException('Unauthorized – There was an issue with your API credentials.', _context) + elif _context.response.status_code == 403: + raise ErrorException('Forbidden – The server understood the request but refuses to authorize it.', _context) elif _context.response.status_code == 404: raise ErrorException('The specified resource was not found', _context) self.validate_response(_context) From 96c986544662b82025ca32f39585c24a06f6ce4b Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Tue, 9 Jan 2018 16:33:25 -0800 Subject: [PATCH 04/17] Update user agent header --- flowroutenumbersandmessaging/controllers/base_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flowroutenumbersandmessaging/controllers/base_controller.py b/flowroutenumbersandmessaging/controllers/base_controller.py index cc6d5e9..ed58f27 100644 --- a/flowroutenumbersandmessaging/controllers/base_controller.py +++ b/flowroutenumbersandmessaging/controllers/base_controller.py @@ -32,7 +32,7 @@ class BaseController(object): http_call_back = None global_headers = { - 'user-agent': 'APIMATIC 2.0' + 'user-agent': 'Flowroute SDK v3' } def __init__(self, client=None, call_back=None): From 05a6d1b3ecb1a982c99885cc986428529cbd5f55 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Tue, 9 Jan 2018 17:15:20 -0800 Subject: [PATCH 05/17] Print List Phone Number Details result and add limit to Look Up a Set of Messages --- demo.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/demo.py b/demo.py index 50cce59..df0b836 100755 --- a/demo.py +++ b/demo.py @@ -50,8 +50,8 @@ result = numbers_controller.search_for_purchasable_phone_numbers(starts_with, co pprint.pprint(result) print("--Purchase a Phone Number") -number_id = result['data'][0]['id'] -#result = numbers_controller.purchase_a_phone_number(number_id) +purchasable_number = result['data'][0]['id'] +#result = numbers_controller.purchase_a_phone_number(purchasable_number) print("--List Account Phone Numbers") starts_with = 201 @@ -66,6 +66,7 @@ pprint.pprint(result) print("--List Phone Number Details") number_id = result['data'][0]['id'] result = numbers_controller.list_phone_number_details(number_id) +print result print ("---List Inbound Routes") limit = 3 @@ -123,7 +124,8 @@ print ("---Send A Message") print ("---Look Up A Set Of Messages") start_date = "2017-12-01" end_date = "2018-01-08" -result = messages_controller.look_up_a_set_of_messages(start_date, end_date) +limit = 2 +result = messages_controller.look_up_a_set_of_messages(start_date, end_date, limit) pprint.pprint(result) print ("---Look Up A Message Detail Record") From 8622ac4a9511421cfc572ba2bed20d3df7dcd318 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Wed, 10 Jan 2018 16:06:38 -0800 Subject: [PATCH 06/17] Clean up example responses and reorganize content --- README.md | 281 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 213 insertions(+), 68 deletions(-) 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) ``` From d53652d5cccf2e621bbdd2d501cd825ae088bf97 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Wed, 10 Jan 2018 16:11:04 -0800 Subject: [PATCH 07/17] Reorganize content --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c1ea940..c320b5d 100644 --- a/README.md +++ b/README.md @@ -643,10 +643,12 @@ else: ``` ##### 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. +`204: No 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` @@ -797,7 +799,7 @@ On success, the HTTP status code in the response header is `200 OK` and the resp "timestamp": "2017-12-22T01:52:39.39Z", "delivery_receipts": [], "amount_display": "$0.0040", - "from": "12067392634", + "from": "12061232634", "is_mms": false, "message_type": "longcode" }, From 3d7907a29ce1d2d73b97fd890494dbc75c18df86 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Wed, 10 Jan 2018 23:20:50 -0800 Subject: [PATCH 08/17] Update Send a Message description and set unique value for alias --- README.md | 1 + demo.py | 43 ++++++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index c320b5d..cfc608a 100644 --- a/README.md +++ b/README.md @@ -675,6 +675,7 @@ print ("---Send A Message") result = messages_controller.send_a_message(request_body) pprint.pprint(result) ``` +Note that this function call is currently commented out. Uncomment to test the `send_a_message` method. ##### Example Response diff --git a/demo.py b/demo.py index df0b836..cdae312 100755 --- a/demo.py +++ b/demo.py @@ -66,7 +66,28 @@ pprint.pprint(result) print("--List Phone Number Details") number_id = result['data'][0]['id'] result = numbers_controller.list_phone_number_details(number_id) -print result +pprint.pprint(result) + +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 = id_generator() +for i in range(10): + alias += str(i) +request_body = '{ \ + "data": { \ + "type": "route", \ + "attributes": { \ + "route_type": "host", \ + "value": "' + new_route +'", \ + "alias": "' + alias + '" \ + } \ + } \ +}' +result = routes_controller.create_an_inbound_route(request_body) +pprint.pprint(result) print ("---List Inbound Routes") limit = 3 @@ -134,23 +155,3 @@ result = messages_controller.look_up_a_message_detail_record(message_id) pprint.pprint(result) -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": "host", \ - "value": "' + new_route +'", \ - "alias": "' + alias + '" \ - } \ - } \ -}' -result = routes_controller.create_an_inbound_route(request_body) -print result From 5bc645121de83318b98196667c3eaaf8317ba7fc Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Wed, 10 Jan 2018 23:28:15 -0800 Subject: [PATCH 09/17] Update Create an Inbound Route description --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cfc608a..e3df46c 100644 --- a/README.md +++ b/README.md @@ -491,7 +491,7 @@ Flowroute SDK version 3 for Python allows you to make HTTP requests to the `rout #### create\_an\_inbound\_route(route\_body) -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. +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. We use the same function to generate a unique `alias`. ##### Example Request ```python @@ -500,8 +500,8 @@ print ("---Create an Inbound Route") 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) +alias = id_generator() +for i in range(6): alias += str(i) print new_route request_body = '{ \ "data": { \ From 93a2f0f705a678cb3a79aa3123b770db8796d828 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Thu, 11 Jan 2018 13:17:30 -0800 Subject: [PATCH 10/17] Test SDK with Python3, update user-agent info, remove duplicate error handling --- README.md | 13 ++++++++++--- demo.py | 19 +++++++++---------- .../controllers/base_controller.py | 2 +- .../controllers/routes_controller.py | 13 ++++++------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index e3df46c..32a69e5 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ Requirements ------------ * Flowroute [API credentials](https://manage.flowroute.com/accounts/preferences/api/) -* [Python](https://www.python.org/downloads/) 2.x or higher +* [Python](https://www.python.org/downloads/) `2 >=2.7.9` or `3 >=3.4` + * * * Installation @@ -32,9 +33,15 @@ Installation * via SSH: `git@github.com:flowroute/flowroute-numbers-messaging-python.git` -2. Switch to the newly-created `flowroute-numbers-messaging-python` directory. Version 3 of the Flowroute SDK for Python comes with a requirements file listing the required Python libraries. Click [here](https://packaging.python.org/installing/#requirements-files) to learn more about different ways to install Python packages. Depending on your `pip` permissions, you may be required to preface each `pip` command with `sudo`. +2. Switch to the newly-created `flowroute-numbers-messaging-python` directory. To build and install the required modules, run the following: +`python setup.py install` + +3. Version 3 of the Flowroute SDK for Python comes with a requirements file listing the required Python libraries. Click [here](https://packaging.python.org/installing/#requirements-files) to learn more about different ways to install Python packages. `pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `2.7.9` and `3.6.4`. To see which version of `pip` is installed on your machine, run the following: +`pip --version` + +Depending on your `pip` permissions, you may be required to preface each `pip` command with `sudo`. -`pip install -r requirements.txt` +`pip3 install -r requirements.txt` * * * Usage diff --git a/demo.py b/demo.py index cdae312..a85ad3b 100755 --- a/demo.py +++ b/demo.py @@ -4,7 +4,6 @@ import os import json import random import string -import requests from flowroutenumbersandmessaging.flowroutenumbersandmessaging_client import FlowroutenumbersandmessagingClient from flowroutenumbersandmessaging.models import * from flowroutenumbersandmessaging.models.new_route import NewRoute @@ -68,7 +67,7 @@ number_id = result['data'][0]['id'] result = numbers_controller.list_phone_number_details(number_id) pprint.pprint(result) -print ("---Create an Inbound Route") +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)) @@ -104,12 +103,12 @@ request_body = '{ \ } \ }' -print ("---Update Primary Voice Route") +print("---Update Primary Voice Route") result = routes_controller.update_primary_voice_route(number_id, request_body) if result is None: - print "204: No Content" + print("204: No Content") else: - print result + print (result) request_body = '{ \ "data": { \ @@ -118,12 +117,12 @@ request_body = '{ \ } \ }' -print ("---Update Failover Voice Route") +print("---Update Failover Voice Route") result = routes_controller.update_failover_voice_route(number_id, request_body) if result is None: - print "204: No Content" + print("204: No Content") else: - print result + print (result) request_body = '{ \ "data": { \ @@ -138,11 +137,11 @@ request_body = '{ \ } \ }' -print ("---Send A Message") +print("---Send A Message") #result = messages_controller.send_a_message(request_body) #pprint.pprint(result) -print ("---Look Up A Set Of Messages") +print("---Look Up A Set Of Messages") start_date = "2017-12-01" end_date = "2018-01-08" limit = 2 diff --git a/flowroutenumbersandmessaging/controllers/base_controller.py b/flowroutenumbersandmessaging/controllers/base_controller.py index ed58f27..fa1dc27 100644 --- a/flowroutenumbersandmessaging/controllers/base_controller.py +++ b/flowroutenumbersandmessaging/controllers/base_controller.py @@ -32,7 +32,7 @@ class BaseController(object): http_call_back = None global_headers = { - 'user-agent': 'Flowroute SDK v3' + 'user-agent': 'Flowroute SDK v3.0' } def __init__(self, client=None, call_back=None): diff --git a/flowroutenumbersandmessaging/controllers/routes_controller.py b/flowroutenumbersandmessaging/controllers/routes_controller.py index 660392d..b43c61e 100644 --- a/flowroutenumbersandmessaging/controllers/routes_controller.py +++ b/flowroutenumbersandmessaging/controllers/routes_controller.py @@ -47,8 +47,8 @@ class RoutesController(BaseController): # Prepare headers _headers = { - 'accept': 'application/vnd.api+json', - 'content-type': 'application/vnd.api+json; charset=utf-8' + 'accept': 'application/json', + 'content-type': 'application/json; charset=utf-8' } # Prepare and execute request @@ -58,13 +58,14 @@ class RoutesController(BaseController): # Endpoint and global error handling using HTTP status codes. if _context.response.status_code == 401: - raise ErrorException('Unauthorized – There was an issue with your API credentials.', _context) + raise ErrorException('401 Unauthorized – There was an issue with your API credentials.', _context) elif _context.response.status_code == 403: - raise ErrorException('Forbidden – The server understood the request but refuses to authorize it.', _context) + raise ErrorException('403 Forbidden – The server understood the request but refuses to authorize it.', _context) elif _context.response.status_code == 404: - raise ErrorException('The specified resource was not found', _context) + raise ErrorException('404 The specified resource was not found', _context) self.validate_response(_context) + # Return appropriate type return APIHelper.json_deserialize(_context.response.raw_body) @@ -118,8 +119,6 @@ class RoutesController(BaseController): raise APIException('Unauthorized', _context) elif _context.response.status_code == 404: raise APIException('Not Found', _context) - elif _context.response.status_code <> 200: - raise ErrorException('Unspecified error occurred', _context) self.validate_response(_context) return APIHelper.json_deserialize(_context.response.raw_body) From 20b3d2609139ac7899c1112389c1171593f085f8 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Thu, 11 Jan 2018 13:30:59 -0800 Subject: [PATCH 11/17] Update formatting of Requirements --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 32a69e5..e346a31 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Requirements ------------ * Flowroute [API credentials](https://manage.flowroute.com/accounts/preferences/api/) -* [Python](https://www.python.org/downloads/) `2 >=2.7.9` or `3 >=3.4` +* [Python](https://www.python.org/downloads/): `Python 2 >=2.7.9` or `Python 3 >=3.4` * * * @@ -34,9 +34,11 @@ Installation * via SSH: `git@github.com:flowroute/flowroute-numbers-messaging-python.git` 2. Switch to the newly-created `flowroute-numbers-messaging-python` directory. To build and install the required modules, run the following: + `python setup.py install` 3. Version 3 of the Flowroute SDK for Python comes with a requirements file listing the required Python libraries. Click [here](https://packaging.python.org/installing/#requirements-files) to learn more about different ways to install Python packages. `pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `2.7.9` and `3.6.4`. To see which version of `pip` is installed on your machine, run the following: + `pip --version` Depending on your `pip` permissions, you may be required to preface each `pip` command with `sudo`. From 2bbbdb2bc66cc0251942634cf17b7b00d6e78151 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Thu, 11 Jan 2018 15:14:25 -0800 Subject: [PATCH 12/17] Update directory name and installation section --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e346a31..69cbf80 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,9 @@ Installation * via SSH: `git@github.com:flowroute/flowroute-numbers-messaging-python.git` -2. Switch to the newly-created `flowroute-numbers-messaging-python` directory. To build and install the required modules, run the following: +2. Switch to the newly-created `flowroute-sdk-v3-python` directory. This version of the SDK comes with a requirements file listing the required Python libraries. Click [here](https://packaging.python.org/installing/#requirements-files) to learn more about different ways to install Python packages. -`python setup.py install` - -3. Version 3 of the Flowroute SDK for Python comes with a requirements file listing the required Python libraries. Click [here](https://packaging.python.org/installing/#requirements-files) to learn more about different ways to install Python packages. `pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `2.7.9` and `3.6.4`. To see which version of `pip` is installed on your machine, run the following: +`pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `Python 2.7.9` and `Python 3.6.4`. To see which version of `pip` is installed on your machine, run the following: `pip --version` From d6becc85cb552df3ab8c542a0dedd55d2f13bf41 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Thu, 11 Jan 2018 15:18:36 -0800 Subject: [PATCH 13/17] Update installation content --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 69cbf80..aafa8dc 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ Installation * via SSH: `git@github.com:flowroute/flowroute-numbers-messaging-python.git` -2. Switch to the newly-created `flowroute-sdk-v3-python` directory. This version of the SDK comes with a requirements file listing the required Python libraries. Click [here](https://packaging.python.org/installing/#requirements-files) to learn more about different ways to install Python packages. +2. Switch to the newly-created `flowroute-sdk-v3-python` directory. This version of the SDK comes with a requirements file listing the required Python libraries. See [Installing Packages](https://packaging.python.org/tutorials/installing-packages/) to learn more about different ways to install Python packages. -`pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `Python 2.7.9` and `Python 3.6.4`. To see which version of `pip` is installed on your machine, run the following: +`pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `Python 2.7.9` and `Python 3.6.4` for Mac OS X. To see which version of `pip` is installed on your machine, run the following: `pip --version` From cc5cdd5bbd0e5eb455c8ba699840911ead25867a Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Mon, 15 Jan 2018 14:49:02 -0800 Subject: [PATCH 14/17] Remove unnecessary imports and use consistent wording in documentation --- README.md | 27 +++++++++++++-------------- demo.py | 2 -- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index aafa8dc..e885ba3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -Flowroute SDK for Python (v3) +Flowroute Python Library v3 ===================== -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. +The Flowroute Python library 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** @@ -28,25 +28,25 @@ Requirements Installation ------------ -1. First, start a shell session and clone the SDK: - * via HTTPS: `git clone https://github.com/flowroute/flowroute-numbers-messaging-python.git` +1. First, start a shell session and clone the Python library: + * via HTTPS: `git clone https://github.com/flowroute/flowroute-sdk-v3-python.git` - * via SSH: `git@github.com:flowroute/flowroute-numbers-messaging-python.git` + * via SSH: `git@github.com:flowroute/flowroute-sdk-v3-python.git` -2. Switch to the newly-created `flowroute-sdk-v3-python` directory. This version of the SDK comes with a requirements file listing the required Python libraries. See [Installing Packages](https://packaging.python.org/tutorials/installing-packages/) to learn more about different ways to install Python packages. +2. Switch to the newly-created `flowroute-sdk-v3-python` directory. This version of the library comes with a requirements file listing the required Python libraries. See [Installing Packages](https://packaging.python.org/tutorials/installing-packages/) to learn more about different ways to install Python packages. -`pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This SDK has been tested with both `Python 2.7.9` and `Python 3.6.4` for Mac OS X. To see which version of `pip` is installed on your machine, run the following: +`pip` is already installed if you're using `Python 2 >=2.7.9` or `Python 3 >=3.4`. This version of the library has been tested with both `Python 2.7.9` and `Python 3.6.4` for Mac OS X. To see which version of `pip` is installed on your machine, run the following: `pip --version` -Depending on your `pip` permissions, you may be required to preface each `pip` command with `sudo`. +Depending on your `pip` permissions, you may be required to preface each `pip` command with `sudo`. `pip3 install -r requirements.txt` * * * 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. +In Flowroute's approach to building the Python library v3, 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 library. ## Controllers @@ -78,7 +78,7 @@ Contains the methods required to send an MMS or SMS, and review a specific Messa * [look\_up\_a\_message\_detail\_record()](#look_up_a_message_detail_recordmessage_id) \- Searches for a specific message record ID and returns a Message Detail Record (in MDR2 format). * [look\_up\_a\_set\_of\_messages()](#look_up_a_set_of_messagesstart_date) \- Retrieves a list of Message Detail Records (MDRs) within a specified date range. Date and time is based on Coordinated Universal Time (UTC). -The following shows an example of a single Python file that imports the Flowroute API client and all the required modules. The Python SDK comes with a **demo.py** file that you can edit and run as an example. +The following shows an example of a single Python file that imports the Flowroute API client and all the required modules. The Python library v3 comes with a **demo.py** file that you can edit and run as an example. ```python import pprint @@ -86,7 +86,6 @@ import os import json import random import string -import requests from flowroutenumbersandmessaging.flowroutenumbersandmessaging_client import FlowroutenumbersandmessagingClient ``` #### Credentials @@ -114,7 +113,7 @@ The following section will demonstrate the capabilities of Numbers v2 and Messag ### Number Management -Flowroute SDK version 3 for Python allows you to make HTTP requests to the `numbers` resource of Flowroute API v2: `https://api.flowroute.com/v2/numbers` +The Flowroute Python library v3 allows you to make HTTP requests to the `numbers` resource of Flowroute API v2: `https://api.flowroute.com/v2/numbers` #### list\_available\_area\_codes() @@ -494,7 +493,7 @@ On success, the HTTP status code in the response header is `200 OK` and the resp ### Route Management -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` +The Flowroute Python library v3 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) @@ -657,7 +656,7 @@ On success, the HTTP status code in the response header is `204 No Content` whic ### 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` +The Flowroute Python library v3 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) diff --git a/demo.py b/demo.py index a85ad3b..d1e0778 100755 --- a/demo.py +++ b/demo.py @@ -5,8 +5,6 @@ import json import random import string from flowroutenumbersandmessaging.flowroutenumbersandmessaging_client import FlowroutenumbersandmessagingClient -from flowroutenumbersandmessaging.models import * -from flowroutenumbersandmessaging.models.new_route import NewRoute print("Number/Route Management v2 & Messaging v2.1 Demo") From 5c257f8f973202b8150beb4d5981b0504b3a3ff5 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Tue, 23 Jan 2018 11:49:39 -0800 Subject: [PATCH 15/17] Add to TOC and include testing section --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index e885ba3..3afd7c1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,26 @@ The Flowroute Python library v3 provides methods for interacting with [Numbers v * [Messages Controller](#messagescontroller) * [Credentials](#credentials) * [Methods](#methods) + * [Number Management](#number-management) + * [list_available_area_codes](#list_available_area_codes) + * [list_available_exchange_codes](#list_available_exchange_codes) + * [search_for_purchasable_phone_numbers](#search_for_purchasable_phone_numbers) + * [purchase_a_phone_number](#purchase_a_phone_numberpurchasable_number) + * [list_account_phone_numbers](#list_account_phone_numbers) + * [list_phone_number_details](#list_phone_number_detailsnumber_id) + + * [Route Management](#route-management) + * [create_an_inbound_route](#create_an_inbound_routeroute_body) + * [list_inbound_routes](#list_inbound_routes) + * [update_primary_voice_route](#update_primary_voice_routenumber_id-route_body) + * [update_failover_voice_route](#update_failover_voice_routenumber_id-route_body) + + * [Messaging](#messaging) + * [send_a_message](#send_a_messagemessage_body) + * [look_up_a_set_of_messagesstart_date](#look_up_a_set_of_messagesstart_date) + * [look_up_a_message_detail_record](#look_up_a_message_detail_recordmessage_id) * [Errors](#errors) + * [Testing](#testing) * * * Requirements @@ -824,3 +843,8 @@ In cases of method errors, the Python library raises an exception which includes raise ErrorException('403 Forbidden – The server understood the request but refuses to authorize it.', _context) ``` +## Testing + +Once you are done configuring your Flowroute API credentials and updating the function parameters, run the file to see the demo in action: + +` ruby demo.rb ` From 029b9094532a8a4af7f6ad84d3db22bd638f6ece Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Wed, 24 Jan 2018 14:08:48 -0800 Subject: [PATCH 16/17] Update testing command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3afd7c1..834b13e 100644 --- a/README.md +++ b/README.md @@ -847,4 +847,4 @@ raise ErrorException('403 Forbidden – The server understood the request but re Once you are done configuring your Flowroute API credentials and updating the function parameters, run the file to see the demo in action: -` ruby demo.rb ` +` python demo.py ` From e53bd650baa4cbc86f581f31153cd681893fa105 Mon Sep 17 00:00:00 2001 From: Maria Bermudez Date: Mon, 19 Feb 2018 14:15:52 -0800 Subject: [PATCH 17/17] Add latest Flowroute Swagger spec. --- Numbers-Messaging-Callbacks-E911_APIs.json | 2171 ++++++++++++++++++++ 1 file changed, 2171 insertions(+) create mode 100644 Numbers-Messaging-Callbacks-E911_APIs.json diff --git a/Numbers-Messaging-Callbacks-E911_APIs.json b/Numbers-Messaging-Callbacks-E911_APIs.json new file mode 100644 index 0000000..5e7bab5 --- /dev/null +++ b/Numbers-Messaging-Callbacks-E911_APIs.json @@ -0,0 +1,2171 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Flowroute APIs", + "description": "The Flowroute APIs are organized around REST. Our APIs have resource-oriented URLs, support HTTP Verbs, and respond with HTTP Status Codes. All API requests and responses, including errors, will be represented as JSON objects. You can use the Flowroute APIs to manage your Flowroute phone numbers including setting primary and failover routes for inbound calls, and sending text messages (SMS and MMS) using long-code or toll-free numbers in your account.", + "version": "0.1.1" + }, + "servers": [ + { + "url": "https://api.flowroute.com/", + "description": "Main (production) server" + }, + { + "url": "https://api.staging.fl.gg/", + "description": "Staging server" + } + ], + "security": [ + { + "basicAuth": [] + } + ], + "paths": { + "/v2.1/messages": { + "post": { + "summary": "Send a Message", + "description": "Sends an SMS or MMS from a Flowroute long code or toll-free phone number to another valid phone number.", + "requestBody": { + "description": "The SMS or MMS message to send.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "tags": [ + "messages" + ], + "responses": { + "202": { + "description": "ACCEPTED", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/MessageSuccess" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + }, + "get": { + "summary": "Look Up a Set of Messages", + "description": "Retrieves a list of Message Detail Records (MDRs) within a specified date range. Date and time is based on Coordinated Universal Time (UTC).", + "parameters": [ + { + "in": "query", + "name": "start_date", + "required": true, + "schema": { + "type": "string", + "format": "date-time", + "example": "2017-12-01T00:00:00.000Z" + }, + "description": "The beginning date and time, in UTC, on which to perform an MDR search. The DateTime can be formatted as YYYY-MM-DDor YYYY-MM-DDTHH:mm:ss.SSZ." + }, + { + "in": "query", + "name": "end_date", + "required": false, + "schema": { + "type": "string", + "format": "date-time", + "example": "2017-12-06T00:00:00.000Z" + }, + "description": "The ending date and time, in UTC, on which to perform an MDR search. The DateTime can be formatted as YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss.SSZ." + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "The number of MDRs to retrieve at one time. You can set as high of a number as you want, but the number cannot be negative and must be greater than 0 (zero)." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "The number of MDRs to skip when performing a query. The number must be 0 (zero) or greater, but cannot be negative." + } + ], + "tags": [ + "messages" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/MDRSet" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2.1/messages/{id}": { + "get": { + "summary": "Look Up a Message Detail Record", + "description": "Searches for a specific message record ID and returns a Message Detail Record (in MDR2 format).", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + }, + "description": "The unique message detail record identifier (MDR ID) of any message. When entering the MDR ID, the number should include the mdr2- preface." + } + ], + "tags": [ + "messages" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/MDR2" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2.1/messages/{callback_type}": { + "put": { + "summary": "Set a Callback URL for Your Account", + "description": "Lets you assign a callback URL for POST notifications of inbound SMS or MMS messages to your Flowroute long code or toll-free phone number, or delivery receipts (DLRs) of SMS messages that you have sent from your Flowroute long code or toll-free number.", + "parameters": [ + { + "in": "path", + "name": "callback_type", + "required": true, + "schema": { + "type": "string" + }, + "description": "Callback type to be associated with the account. Possible values are sms_callback, mms_callback, and dlr_callback." + } + ], + "requestBody": { + "description": "The callback URL for your specified callback type.", + "required": false, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "callback_url": { + "type": "string", + "format": "url" + } + } + } + } + } + }, + "tags": [ + "callbacks" + ], + "responses": { + "204": { + "description": "NO CONTENT" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "405": { + "$ref": "#/components/responses/MethodNotAllowed" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + }, + "get": { + "summary": "Look Up Callback Details for Your Account", + "description": "Lets you retrieve the callback information for your inbound SMS, inbound MMS, or outbound delivery receipt (DLR) callback service.", + "parameters": [ + { + "in": "path", + "name": "callback_type", + "required": true, + "schema": { + "type": "string" + }, + "description": "Callback type to be associated with the account. Options are sms_callback, mms_callback, anf dlr_callback." + }, + { + "in": "query", + "name": "number", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "in": "query", + "name": "callback", + "required": false, + "schema": { + "type": "integer" + } + } + ], + "tags": [ + "callbacks" + ], + "responses": { + "200": { + "description": "A JSON object of phone numbers in your account", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/Callback" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "summary": "Remove Callback Details For Your Account", + "description": "Lets you delete the associated URL for your inbound SMS, inbound MMS, or outbound delivery receipt (DLR) callback service.", + "parameters": [ + { + "in": "path", + "name": "callback_type", + "required": true, + "schema": { + "type": "string" + }, + "description": "Callback type associated with the URL to be removed from the account. Options are sms_callback, mms_callback, anf dlr_callback." + } + ], + "tags": [ + "callbacks" + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/{id}/relationships/{callback_type}": { + "post": { + "summary": "Set a Messaging Callback URL for Your Phone Number", + "description": "Lets you assign a messaging callback URL to a specific long code or toll-free phone number in your account for POST notifications of inbound SMS or MMS messages, or delivery receipts (DLRs) of SMS messages you have sent from that number.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number to be associated with the messaging callback URL." + }, + { + "in": "path", + "name": "callback_type", + "required": true, + "schema": { + "type": "string" + }, + "description": "Callback type to be associated with the specified phone number. Options are sms_callback, mms_callback, and dlr_callback." + } + ], + "requestBody": { + "description": "The callback URL to be assigned to the phone number.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/DIDCallback" + } + } + } + }, + "tags": [ + "callbacks" + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + }, + "get": { + "summary": "Look Up Callback Details for Your Phone Number", + "description": "Lets you retrieve the URL information for the inbound SMS, inbound MMS, or delivery receipt (DLR) callback service of your long code or toll-free phone number.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number associated with the callback service." + }, + { + "in": "path", + "name": "callback_type", + "required": true, + "schema": { + "type": "string" + }, + "description": "Callback type of the callback service to retrieve details for. Options are sms_callback, mms_callback, anf dlr_callback." + } + ], + "tags": [ + "callbacks" + ], + "responses": { + "200": { + "description": "A detailed callback object in JSON format.", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/Callback" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "summary": "Remove Callback Details For Your Phone Number", + "description": "Lets you delete the associated URL for the inbound SMS, inbound MMS, or outbound delivery receipt (DLR) callback service of your phone number.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number associated with the callback URL to be deleted." + }, + { + "in": "path", + "name": "callback_type", + "required": true, + "schema": { + "type": "string" + }, + "description": "Callback type associated with the URL to be deleted for your specified phone number. Options are sms_callback, mms_callback, anf dlr_callback." + } + ], + "tags": [ + "callbacks" + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/{id}/relationships/e911": { + "patch": { + "summary": "Assign a Valid E911 Address to Your Phone Number", + "description": "Lets you assign a valid E911 address to a specific long code or toll-free phone number in your account.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number to be associated with the valid E911 address." + } + ], + "requestBody": { + "description": "The valid E911 record to be assigned to the long code or toll-free phone number.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "e911" + }, + "id": { + "type": "integer" + } + } + } + } + } + } + } + }, + "tags": [ + "e911, callbacks" + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + }, + "delete": { + "summary": "Deactivate E911 Service for a Phone Number", + "description": "Lets you deactivate the current E911 service for a phone number.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number associated with the E911 service to be deactivated." + } + ], + "tags": [ + "numbers, e911" + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers": { + "get": { + "summary": "Account Phone Numbers", + "description": "Returns a list of all phone numbers currently on your Flowroute account. The response includes details such as the phone number's rate center, state, number type, and whether CNAM Lookup is enabled for that number.", + "parameters": [ + { + "in": "query", + "name": "starts_with", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Retrieves phone numbers that start with the specified value." + }, + { + "in": "query", + "name": "ends_with", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Retrieves phone numbers that end with the specified value." + }, + { + "in": "query", + "name": "contains", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Retrieves phone numbers containing the specified value." + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Limits the number of items to retrieve. A maximum of 200 items can be retrieved." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Offsets the list of phone numbers by your specified value. For example, if you have 4 phone numbers and you entered 1 as your offset value, then only 3 of your phone numbers will be displayed in the response." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "200": { + "description": "A JSON object of phone numbers in your account", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/Numbers" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/{id}": { + "get": { + "summary": "Phone Number Details", + "description": "Lists all of the information associated with any of the phone numbers in your account, including billing method, primary voice route, and failover voice route.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "Phone number to search for which must be a number that you own. Must be in 11-digit E.164 format; e.g. 12061231234." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "200": { + "description": "A JSON object of phone numbers in your account", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/Number" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + } + }, + "delete": { + "summary": "Delete a Phone Number From Your Account", + "description": "Lets you delete a phone number from your account.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "Phone number to be removed from your account. Must be in 11-digit E.164 format; e.g. 12061231234." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "204": { + "description": "No Response" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + } + }, + "post": { + "summary": "Purchase a Phone Number", + "description": "Lets you purchase a phone number from available Flowroute inventory.", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "Phone number to purchase. Must be in 11-digit E.164 format; e.g. 12061231234." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "201": { + "description": "CREATED", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/Number" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/available": { + "get": { + "summary": "Search for Purchasable Phone Numbers", + "description": "This endpoint lets you search for phone numbers by state or rate center, or by your specified search value.", + "parameters": [ + { + "in": "query", + "name": "starts_with", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Retrieve phone numbers that start with the specified value." + }, + { + "in": "query", + "name": "contains", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Retrieve phone numbers containing the specified value." + }, + { + "in": "query", + "name": "ends_with", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Retrieve phone numbers that end with the specified value." + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Limits the number of items to retrieve. A maximum of 200 items can be retrieved." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Offsets the list of phone numbers by your specified value. For example, if you have 4 phone numbers and you entered 1 as your offset value, then only 3 of your phone numbers will be displayed in the response." + }, + { + "in": "query", + "name": "rate_center", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filters by and displays phone numbers in the specified case-insensitive abbreviated rate center, not the full name as differentiated in the NPA Rate Center Reports." + }, + { + "in": "query", + "name": "state", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filters by and displays phone numbers in the specified case-insensitive two-character abbreviated state. For example, WA for Washington." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "$ref": "#/components/schemas/PurchasableNumbers" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/available/areacodes": { + "get": { + "summary": "List Available Area Codes", + "description": "Returns a list of all Numbering Plan Area (NPA) codes containing purchasable phone numbers.", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Limits the number of items to retrieve. A maximum of 400 items can be retrieved." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Offsets the list of phone numbers by your specified value. For example, if you have 4 phone numbers and you entered 1 as your offset value, then only 3 of your phone numbers will be displayed in the response." + }, + { + "in": "query", + "name": "max_setup_cost", + "required": false, + "schema": { + "type": "number", + "format": "float" + }, + "description": "Restricts the results to area codes that include at least one telephone number with a setup fee below or equal to the specified max_setup_cost. For more details around pricing, please see Flowroute Pricing Details." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/AvailableCodes" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/available/exchanges": { + "get": { + "summary": "List Available Exchange Codes", + "description": "Returns a list of all Central Office (exchange) codes containing purchasable phone numbers.", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Limits the number of items to retrieve. A maximum of 200 items can be retrieved." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Offsets the list of phone numbers by your specified value. For example, if you have 4 phone numbers and you entered 1 as your offset value, then only 3 of your phone numbers will be displayed in the response." + }, + { + "in": "query", + "name": "max_setup_cost", + "required": false, + "schema": { + "type": "number", + "format": "float" + }, + "description": "Restricts the results to exchanges that include at least one telephone number with a setup fee below or equal to the specified max_setup_cost. For more details around pricing, please see Flowroute Pricing Details." + }, + { + "in": "query", + "name": "areacode", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Restricts the results to the specified area code." + } + ], + "tags": [ + "numbers" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/AvailableCodes" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/{number_id}/relationships/primary_route": { + "patch": { + "summary": "Update Primary Voice Route for a Phone Number", + "description": "Use this endpoint to update the primary voice route for a phone number. You must create the route first by following \"Create an Inbound Route\". You can then assign the created route by specifying its value in a PATCH request.", + "parameters": [ + { + "in": "path", + "name": "number_id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number in E.164 11-digit North American format to which the primary route for voice will be assigned." + } + ], + "requestBody": { + "description": "The primary route to be assigned.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Routes" + } + } + } + }, + "tags": [ + "routes" + ], + "responses": { + "204": { + "description": "NO CONTENT" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/numbers/{number_id}/relationships/failover_route": { + "patch": { + "summary": "Update Failover Voice Route for a Phone Number", + "description": "Use this endpoint to update the failover voice route for a phone number. You must create the route first by following \"Create an Inbound Route\". You can then assign the created route by specifying its value in a PATCH request.", + "parameters": [ + { + "in": "path", + "name": "number_id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The phone number in E.164 11-digit North American format to which the failover route for voice will be assigned." + } + ], + "requestBody": { + "description": "The failover route to be assigned.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Routes" + } + } + } + }, + "tags": [ + "routes" + ], + "responses": { + "204": { + "description": "NO CONTENT" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/routes": { + "post": { + "summary": "Create an Inbound Route", + "description": "Creates a new inbound route which can then be associated with phone numbers. Please see \"List Inbound Routes\" to review the route values that you can associate with your Flowroute phone numbers.", + "requestBody": { + "description": "The new inbound route to be created.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/NewRoute" + } + } + } + }, + "tags": [ + "routes" + ], + "responses": { + "201": { + "description": "CREATED" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "get": { + "summary": "List Inbound Routes", + "description": "Returns a list of your inbound routes. From the list, you can then select routes to use as the primary and failover routes for a phone number, which you can do via \"Update Primary Voice Route for a Phone Number\" and \"Update Failover Voice Route for a Phone Number\".", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Limits the number of routes to retrieve. A maximum of 200 items can be retrieved." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Offsets the list of routes by your specified value. For example, if you have 4 inbound routes and you entered 1 as your offset value, then only 3 of your routes will be displayed in the response." + }, + { + "in": "query", + "name": "route_type", + "required": false, + "schema": { + "type": "string", + "enum": [ + "host", + "sip-reg", + "uri", + "number" + ] + }, + "description": "Restricts the results to inbound routes with your specified route type." + } + ], + "tags": [ + "routes" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/AccountRoutes" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + } + } + }, + "/v2/e911": { + "post": { + "summary": "Create and Validate a New E911 Address", + "description": "Creates and validates a new E911 address.", + "requestBody": { + "description": "The E911 address to be validated.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/E911Address" + } + } + } + }, + "tags": [ + "e911" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/AccountRoutes" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "415": { + "$ref": "#/components/responses/NotValidated" + } + } + }, + "get": { + "summary": "List E911 Addresses", + "description": "Returns a list of E911 addresses on your account. Addresses can be within the US or Canada.", + "parameters": [ + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Limits the number of e911 addresses to retrieve. A maximum of __ items can be retrieved." + }, + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Offsets the list of e911 addresses by your specified value. For example, if you have 4 e911 addresses and you entered 1 as your offset value, then only 3 of your e911 addresses will be displayed in the response." + }, + { + "in": "query", + "name": "state", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filters by and displays E911 addresses in the specified case-insensitive two-character abbreviated state. For example, WA for Washington." + } + ], + "tags": [ + "e911" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "items": { + "$ref": "#/components/schemas/E911Address" + } + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + } + }, + "patch": { + "summary": "Update and Validate an Existing E911 Address", + "description": "Use this endpoint to update and validate an existing E911 address on your account. You must create the E911 address first by following \"Create and Validate a New E911 Address\".", + "parameters": [ + { + "in": "path", + "name": "e911_id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The record ID of the e911 address to be updated." + } + ], + "requestBody": { + "description": "The E911 record to be updated.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/E911Address" + } + } + } + }, + "tags": [ + "e911" + ], + "responses": { + "204": { + "description": "NO CONTENT" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "summary": "Remove an E911 Address From Your Account", + "description": "Lets you delete an E911 address associated with your account.", + "parameters": [ + { + "in": "path", + "name": "e911_id", + "required": true, + "schema": { + "type": "integer" + }, + "description": "The record ID of the E911 address to be removed from your account." + } + ], + "tags": [ + "e911" + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/v2/e911/validate": { + "post": { + "summary": "Validate a New E911 Address", + "description": "Validates a newly created US or Canada E911 address.", + "requestBody": { + "description": "The E911 address to be validated.", + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/E911Address" + } + } + } + }, + "tags": [ + "e911" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/AccountRoutes" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "415": { + "$ref": "#/components/responses/NotValidated" + } + } + } + } + }, + "components": { + "securitySchemes": { + "basicAuth": { + "type": "http", + "scheme": "basic" + } + }, + "schemas": { + "E911Address": { + "type": "object", + "required": [ + "label", + "first_name", + "last_name", + "street_number", + "street_name", + "city", + "state", + "country", + "zip" + ], + "properties": { + "label": { + "type": "string" + }, + "first_name": { + "type": "string" + }, + "last_name": { + "type": "string" + }, + "street_number": { + "type": "string" + }, + "street_name": { + "type": "string" + }, + "address_type": { + "type": "string", + "enum": [ + { + "A": "Apartment" + }, + { + "BM": "Basement" + }, + { + "B": "Building" + }, + { + "D": "Department" + }, + { + "F": "Floor" + }, + { + "FR": "Front" + }, + { + "K": "Key" + }, + { + "L": "Lobby" + }, + { + "LT": "Lot" + }, + { + "LO": "Lower" + }, + { + "O": "Office" + }, + { + "P": "Penthouse" + }, + { + "PI": "Pier" + }, + { + "RE": "Rear" + }, + { + "R": "Room" + }, + { + "S": "Side" + }, + { + "SL": "Slip" + }, + { + "SC": "Space" + }, + { + "SP": "Stop" + }, + { + "SU": "Suite" + }, + { + "T": "Trailer" + }, + { + "U": "Unit" + }, + { + "UP": "Upper" + } + ], + "example": "A" + }, + "address_number": { + "type": "integer" + }, + "city": { + "type": "string" + }, + "state": { + "type": "string" + }, + "country": { + "type": "string", + "enum": [ + "USA", + "Canada" + ], + "example": "USA" + }, + "zip": { + "type": "integer" + } + } + }, + "Message": { + "type": "object", + "required": [ + "from", + "to" + ], + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + }, + "body": { + "type": "string" + }, + "media_urls": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, + "is_mms": { + "type": "boolean" + }, + "dlr_callback": { + "type": "string", + "format": "url" + } + } + }, + "MessageSuccess": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "format": "uri" + } + } + }, + "type": { + "type": "string", + "default": "message", + "example": "message" + } + } + } + } + }, + "MDRSet": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/MDR2" + } + }, + "links": { + "type": "object", + "properties": { + "next": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "MDR2": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "amount_display": { + "type": "number", + "format": "float" + }, + "amount_nanodollars": { + "type": "number" + }, + "body": { + "type": "string" + }, + "delivery_receipts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "level": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "status_code": { + "type": "integer" + }, + "status_code_description": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + } + } + } + }, + "direction": { + "type": "string" + }, + "from": { + "type": "string" + }, + "is_mms": { + "type": "boolean" + }, + "message_encoding": { + "type": "integer" + }, + "message_type": { + "type": "string", + "enum": [ + "longcode", + "toll-free" + ] + }, + "status": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "to": { + "type": "string" + } + } + }, + "id": { + "type": "string" + }, + "relationships": { + "type": "object", + "properties": { + "media": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "default": "media", + "example": "media" + } + } + } + } + } + } + } + }, + "type": { + "type": "string", + "example": "message" + } + } + } + } + }, + "Routes": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "default": "route", + "example": "route" + } + } + } + } + }, + "NewRoute": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "route", + "example": "route" + }, + "attributes": { + "type": "object", + "required": [ + "alias", + "route_type", + "value" + ], + "properties": { + "alias": { + "type": "string" + }, + "route_type": { + "type": "string", + "enum": [ + "sip-reg", + "host", + "uri", + "number" + ], + "default": "sip-reg", + "example": "sip-reg" + }, + "value": { + "type": "string" + } + } + } + } + } + } + }, + "NewRouteResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "$ref": "#/components/schemas/IncludedRoutes" + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "format": "uri", + "example": "https://api.flowroute.com/routes/99670" + } + } + } + } + }, + "AccountRoutes": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/IncludedRoutes" + } + }, + "links": { + "$ref": "#/components/schemas/RequestLinks" + } + } + }, + "IncludedRoutes": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "alias": { + "type": "string" + }, + "route_type": { + "type": "string", + "enum": [ + "host", + "number", + "uri", + "sip-reg" + ], + "default": "sip-reg" + }, + "value": { + "type": "string" + } + } + }, + "id": { + "type": "string" + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "format": "uri" + } + } + }, + "type": { + "type": "string", + "default": "route", + "example": "route" + } + } + }, + "NumberRelationships": { + "type": "object", + "properties": { + "cnam_preset": { + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + }, + "e911_address": { + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + }, + "failover_route": { + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + }, + "primary_route": { + "type": "object", + "$ref": "#/components/schemas/Routes" + } + } + }, + "Number": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "alias": { + "type": "string" + }, + "cnam_lookups_enabled": { + "type": "boolean" + }, + "number_type": { + "type": "string", + "enum": [ + "standard", + "tollfree", + "inum" + ] + }, + "rate_center": { + "type": "string" + }, + "state": { + "type": "string" + }, + "value": { + "type": "integer" + } + } + }, + "id": { + "type": "string" + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + }, + "relationships": { + "type": "object", + "$ref": "#/components/schemas/NumberRelationships" + }, + "type": { + "type": "string", + "default": "number", + "example": "number" + } + } + }, + "included": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/IncludedRoutes" + } + } + } + }, + "Numbers": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/Number" + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "PurchasableNumbers": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "monthly_cost": { + "type": "number", + "format": "double" + }, + "number_type": { + "type": "string", + "enum": [ + "standard", + "tollfree" + ], + "example": "standard" + }, + "rate_center": { + "type": "string" + }, + "setup_cost": { + "type": "number", + "format": "double" + }, + "state": { + "type": "string" + }, + "value": { + "type": "integer" + } + } + }, + "id": { + "type": "string" + }, + "links": { + "$ref": "#/components/schemas/RelatedLinks" + }, + "type": { + "type": "string", + "example": "number" + } + } + } + }, + "links": { + "$ref": "#/components/schemas/RequestLinks" + } + } + }, + "AvailableCodes": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "links": { + "$ref": "#/components/schemas/RelatedLinks" + }, + "type": { + "type": "string", + "enum": [ + "areacode", + "exchange" + ] + } + } + } + }, + "links": { + "$ref": "#/components/schemas/RequestLinks" + } + } + }, + "Callback": { + "properties": { + "data": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "api_version": { + "type": "string" + }, + "callback_url": { + "type": "string" + }, + "product": { + "type": "string" + } + } + }, + "type": { + "type": "string", + "default": "callback", + "example": "callback" + } + } + } + } + }, + "DIDCallback": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "callback_url": { + "type": "string" + } + } + } + } + } + } + }, + "RelatedLinks": { + "type": "object", + "properties": { + "related": { + "type": "string", + "format": "uri", + "example": [ + "https://api.flowroute.com/v2/numbers/12062011204", + "https://api.flowroute.com/v2/numbers/available/exchanges?areacode=202", + "https://api.flowroute.com/v2/numbers/available" + ] + } + } + }, + "RequestLinks": { + "type": "object", + "properties": { + "next": { + "type": "string", + "format": "uri" + }, + "self": { + "type": "string", + "format": "uri" + } + } + }, + "Error": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "status" + ], + "properties": { + "detail": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + } + } + } + } + } + } + }, + "responses": { + "Forbidden": { + "description": "Forbidden – You don't have permission to access this resource.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "NotFound": { + "description": "The specified resource was not found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "NotValidated": { + "description": "Required field not specified", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "Conflict": { + "description": "Records are already associated", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "Unauthorized": { + "description": "Unauthorized – There was an issue with your API credentials.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "MethodNotAllowed": { + "description": "Method Not Allowed – The method is not allowed for the requested URL.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "Unprocessable": { + "description": "Unprocessable Entity - You tried to enter an incorrect value.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } +} \ No newline at end of file