def create_message(self, user_id, body=None): """Does a POST request to /users/{userId}/messages. createMessage Args: user_id (string): TODO: type description here. body (MessageRequest, optional): TODO: type description here. Returns: BandwidthMessage: Response from the API. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/users/{userId}/messages' _url_path = APIHelper.append_url_with_template_parameters(_url_path, { 'userId': user_id }) _query_builder = self.config.get_base_uri(Server.MESSAGINGDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json', 'content-type': 'application/json; charset=utf-8' } # Prepare and execute request _request = self.config.http_client.post(_query_url, headers=_headers, parameters=APIHelper.json_serialize(body)) MessagingBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise MessagingException('400 Request is malformed or invalid', _response) elif _response.status_code == 401: raise MessagingException('401 The specified user does not have access to the account', _response) elif _response.status_code == 403: raise MessagingException('403 The user does not have access to this API', _response) elif _response.status_code == 404: raise MessagingException('404 Path not found', _response) elif _response.status_code == 415: raise MessagingException('415 The content-type of the request is incorrect', _response) elif _response.status_code == 429: raise MessagingException('429 The rate limit has been reached', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize(_response.text, BandwidthMessage.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def handle_messaging_callback(): # raw_data = json.loads(request.data).pop() raw_data = APIHelper.json_deserialize(request.data).pop() messaging_callback: BandwidthCallbackMessage = BandwidthCallbackMessage.from_dictionary( raw_data) message: BandwidthMessage = messaging_callback.message is_dlr = message.direction.lower().strip() == 'out' if is_dlr: log_message = 'Callback Received for: MessageId: %s, status: %s' print(log_message % (message.id, messaging_callback.description)) return 'Received Callback' owner = message.owner to_numbers = message.to.copy() to_numbers.remove(owner) to_numbers.append(message.mfrom) message_request = MessageRequest( application_id=BANDWIDTH_MSG_APPLICATION_ID, to=to_numbers, mfrom=owner) message_text = message.text.lower().strip() is_dog = message_text == 'dog' if is_dog: message_request.text = '🐶' message_request.media = ['https://bw-demo.s3.amazonaws.com/dog.jpg'] else: message_request.text = '👋 Hello From bandwidth!' messaging_client: APIController = bandwidth_client.messaging_client.client api_response: ApiResponse = messaging_client.create_message( BANDWIDTH_ACCOUNT_ID, message_request) message_response: BandwidthMessage = api_response.body log_message = 'Sent message with MessageId: %s' print(log_message % message_response.id) return "Handle messaging callback"
def create_messaging_two_factor(self, account_id, body): """Does a POST request to /accounts/{accountId}/code/messaging. Two-Factor authentication with Bandwidth messaging services Args: account_id (string): Bandwidth Account ID with Messaging service enabled body (TwoFactorCodeRequestSchema): TODO: type description here. Returns: ApiResponse: An object with the response value as well as other useful information such as status codes and headers. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/accounts/{accountId}/code/messaging' _url_path = APIHelper.append_url_with_template_parameters( _url_path, {'accountId': { 'value': account_id, 'encode': True }}) _query_builder = self.config.get_base_uri(Server.TWOFACTORAUTHDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json', 'content-type': 'application/json; charset=utf-8' } # Prepare and execute request _request = self.config.http_client.post( _query_url, headers=_headers, parameters=APIHelper.json_serialize(body)) TwoFactorAuthBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise InvalidRequestException('client request error', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize( _response.text, TwoFactorMessagingResponse.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def __init__(self, reason, response): """Constructor for the ForbiddenRequestException class Args: reason (string): The reason (or error message) for the Exception to be raised. response (HttpResponse): The HttpResponse of the API call. """ super(ForbiddenRequestException, self).__init__(reason, response) dictionary = APIHelper.json_deserialize(self.response.text) if isinstance(dictionary, dict): self.unbox(dictionary)
def list_media(self, user_id, continuation_token=None): """Does a GET request to /users/{userId}/media. listMedia Args: user_id (string): TODO: type description here. continuation_token (string, optional): TODO: type description here. Returns: ApiResponse: An object with the response value as well as other useful information such as status codes and headers. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/users/{userId}/media' _url_path = APIHelper.append_url_with_template_parameters( _url_path, {'userId': { 'value': user_id, 'encode': True }}) _query_builder = self.config.get_base_uri(Server.MESSAGINGDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json', 'Continuation-Token': continuation_token } # Prepare and execute request _request = self.config.http_client.get(_query_url, headers=_headers) MessagingBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise MessagingException('400 Request is malformed or invalid', _response) elif _response.status_code == 401: raise MessagingException( '401 The specified user does not have access to the account', _response) elif _response.status_code == 403: raise MessagingException( '403 The user does not have access to this API', _response) elif _response.status_code == 404: raise MessagingException('404 Path not found', _response) elif _response.status_code == 415: raise MessagingException( '415 The content-type of the request is incorrect', _response) elif _response.status_code == 429: raise MessagingException('429 The rate limit has been reached', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize(_response.text, Media.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def handle_callback(): # Grab the incoming callback information raw_data = APIHelper.json_deserialize(request.data).pop() messaging_callback: BandwidthCallbackMessage = BandwidthCallbackMessage.from_dictionary( raw_data) message: BandwidthMessage = messaging_callback.message # Check the direction of the message - if we are receiving a callback saying our outbound message was sent, # we dont want to reply with another generated trivia question is_dlr = message.direction.lower().strip() == 'out' if is_dlr: """Determine if the message is inbound or outbound and handle it""" log_message = 'Callback Received for: MessageId: %s, status: %s' print(log_message % (message.id, messaging_callback.description)) return 'Outbound Message' question_type = '' question_difficulty = '' question_category = '' question = '' question_correct_answer = '' question_short_answer = '' question_incorrect_answers = '' # Parse the trivia question trivia_question = set_trivia_question() question_type = trivia_question['type'] question_category = trivia_question['category'] question = trivia_question['question'] question_correct_answer = trivia_question['correct_answer'] question_incorrect_answers = trivia_question['incorrect_answers'] if trivia_question['difficulty'] == 'easy': question_difficulty = 1 elif trivia_question['difficulty'] == 'medium': question_difficulty = 2 elif trivia_question['difficulty'] == 'hard': question_difficulty = 3 # Grab the message details and determine if user is new or existing, grab corresponding db record owner = message.owner respondents = message.mfrom database_user = determine_new_user(respondents) database_user.time = datetime.utcnow() # print('Owner', owner) # print('Respondents:', respondents) message_request = MessageRequest( application_id=BANDWIDTH_MSG_APPLICATION_ID, to=respondents, mfrom=owner) # Generate a question/answer set for multiple choice and format True/False if question_type == 'multiple': answers_list = question_incorrect_answers.copy() answers_list.append(question_correct_answer) random.shuffle(answers_list) answers_dict = { 'A': answers_list[0], 'B': answers_list[1], 'C': answers_list[2], 'D': answers_list[3] } # Match the correct letter answer from the dict key with the correct answer value after randomization for key in answers_dict: if question_correct_answer == answers_dict[key]: question_short_answer = str(key) else: pass question_text = str(question) + ' (' + str(question_difficulty) + ' pts.)' + '\n\n' + \ 'A. ' + str(answers_list[0]) + '\n' + 'B. ' + str(answers_list[1]) + '\n' + \ 'C. ' + str(answers_list[2]) + '\n' + 'D. ' + str(answers_list[3]) elif question_type == 'boolean': question_text = 'True or False? (' + str( question_difficulty) + ' pts.)' + '\n\n' + str(question) answers_dict = {'T': 'True', 'F': 'False'} for key in answers_dict: if question_correct_answer == answers_dict[key]: question_short_answer = str(key) else: pass # If user is existing, see if they are sending an answer attempt and match it to the correct answer # held in the database if message.text.lower().strip() == 'new': # If user is requesting a new question, clear their answer field and generate a new question database_user.currentQuestion = question database_user.currentAnswer = question_correct_answer database_user.currentShortAnswer = question_short_answer db.session.commit() message_request.text = str(question_text) + '\n\n' + 'Total Points: ' + str(database_user.points) + \ '\nText \'Help\' for help.\nText \'new\' to generate a new question. ' \ '\nText \'delete\' to permanently delete your account. \nThanks for playing Text Trivia!' messaging_client: APIController = bandwidth_client.messaging_client.client api_response: ApiResponse = messaging_client.create_message( BANDWIDTH_ACCOUNT_ID, message_request) message_response: BandwidthMessage = api_response.body return 'New Question Generated' elif message.text.lower().strip() == 'delete': # If user is requesting account deletion - delete db info TriviaUser.query.filter_by(phoneNumber=respondents).delete() db.session.commit() message_request.text = str( 'Account successfully deleted. ' 'Simply text us again if you\'d like to make a new one!') messaging_client: APIController = bandwidth_client.messaging_client.client api_response: ApiResponse = messaging_client.create_message( BANDWIDTH_ACCOUNT_ID, message_request) message_response: BandwidthMessage = api_response.body return 'Account Deleted' elif message.text.lower().strip() == 'help': # Send a help message with the available message commands message_request.text = 'Text \'new\' to receive a new question.\n\nText \'delete\' to permanently delete ' \ 'your account.\n\nYou can respond to multiple choice questions by either responding ' \ 'with the corresponding letter choice or texting the full answer.\nTrue/False ' \ 'questions can be answered by responding with either T, F, True, or False.' \ '\n\nCurrent Points: ' + str(database_user.points) + '\nMax Points: ' + \ str(database_user.maxPoints) + '\nLives Remaining: ' + str(database_user.lives) messaging_client: APIController = bandwidth_client.messaging_client.client api_response: ApiResponse = messaging_client.create_message( BANDWIDTH_ACCOUNT_ID, message_request) message_response: BandwidthMessage = api_response.body return 'Help is on the way!' elif message.text.lower().strip() == database_user.currentAnswer.lower().strip() or message.text.lower().strip() \ == database_user.currentShortAnswer.lower().strip(): answer_confirmation_text = 'Correct!' # Award points for giving the correct answer database_user.points += int(question_difficulty) if database_user.points > database_user.maxPoints: database_user.maxPoints = int(database_user.points) # set the answer field in the database record to match the newly generated answer database_user.currentQuestion = question database_user.currentAnswer = question_correct_answer database_user.currentShortAnswer = question_short_answer db.session.commit() else: if database_user.currentAnswer == '': answer_confirmation_text = 'Welcome to Text Trivia!' else: answer_confirmation_text = 'Incorrect. The correct answer was ' + \ str(database_user.currentAnswer).strip() + '.' database_user.lives -= 1 if database_user.lives == 0: # Reset current point streak if user runs out of lives database_user.points = 0 database_user.lives = 5 answer_confirmation_text = answer_confirmation_text + '\n\nYou are out of lives! ' \ 'Your points have been reset.' database_user.currentQuestion = question database_user.currentAnswer = question_correct_answer database_user.currentShortAnswer = question_short_answer db.session.commit() new_message_text = str( str(answer_confirmation_text) + '\n\n' + str(question_text) + '\n\n\n' + 'Total Points: ' + str(database_user.points) + '\nLives: ' + str(database_user.lives) + '\nBest Score: ' + str(database_user.maxPoints) + '\n\nThanks for playing Text Trivia!\nText \'Help\' for help.') # Create and send our message using Bandwidht's API message_request.text = new_message_text messaging_client: APIController = bandwidth_client.messaging_client.client api_response: ApiResponse = messaging_client.create_message( BANDWIDTH_ACCOUNT_ID, message_request) message_response: BandwidthMessage = api_response.body return ''
def get_participant(self, account_id, participant_id): """Does a GET request to /accounts/{accountId}/participants/{participantId}. Get participant by ID. Args: account_id (string): Account ID participant_id (string): Participant ID Returns: ApiResponse: An object with the response value as well as other useful information such as status codes and headers. Success Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/accounts/{accountId}/participants/{participantId}' _url_path = APIHelper.append_url_with_template_parameters( _url_path, { 'accountId': { 'value': account_id, 'encode': False }, 'participantId': { 'value': participant_id, 'encode': False } }) _query_builder = self.config.get_base_uri(Server.WEBRTCDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = {'accept': 'application/json'} # Prepare and execute request _request = self.config.http_client.get(_query_url, headers=_headers) WebRtcBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 401: raise APIException('Unauthorized', _response) elif _response.status_code == 403: raise APIException('Access Denied', _response) elif _response.status_code == 404: raise APIException('Not Found', _response) elif (_response.status_code < 200) or (_response.status_code > 208): raise ErrorException('Unexpected Error', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize(_response.text, Participant.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def create_participant(self, account_id, body=None): """Does a POST request to /accounts/{accountId}/participants. Create a new participant under this account. Participants are idempotent, so relevant parameters must be set in this function if desired. Args: account_id (string): Account ID body (Participant, optional): Participant parameters Returns: ApiResponse: An object with the response value as well as other useful information such as status codes and headers. Success Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/accounts/{accountId}/participants' _url_path = APIHelper.append_url_with_template_parameters( _url_path, {'accountId': { 'value': account_id, 'encode': False }}) _query_builder = self.config.get_base_uri(Server.WEBRTCDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json', 'content-type': 'application/json; charset=utf-8' } # Prepare and execute request _request = self.config.http_client.post( _query_url, headers=_headers, parameters=APIHelper.json_serialize(body)) WebRtcBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise APIException('Bad Request', _response) elif _response.status_code == 401: raise APIException('Unauthorized', _response) elif _response.status_code == 403: raise APIException('Access Denied', _response) elif (_response.status_code < 200) or (_response.status_code > 208): raise ErrorException('Unexpected Error', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize( _response.text, AccountsParticipantsResponse.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def get_messages(self, account_id, message_id=None, source_tn=None, destination_tn=None, message_status=None, error_code=None, from_date_time=None, to_date_time=None, page_token=None, limit=None): """Does a GET request to /users/{accountId}/messages. Gets a list of messages based on query parameters. Args: account_id (string): User's account ID message_id (string, optional): The ID of the message to search for. Special characters need to be encoded using URL encoding source_tn (string, optional): The phone number that sent the message destination_tn (string, optional): The phone number that received the message message_status (string, optional): The status of the message. One of RECEIVED, QUEUED, SENDING, SENT, FAILED, DELIVERED, ACCEPTED, UNDELIVERED error_code (int, optional): The error code of the message from_date_time (string, optional): The start of the date range to search in ISO 8601 format. Uses the message receive time. The date range to search in is currently 14 days. to_date_time (string, optional): The end of the date range to search in ISO 8601 format. Uses the message receive time. The date range to search in is currently 14 days. page_token (string, optional): A base64 encoded value used for pagination of results limit (int, optional): The maximum records requested in search result. Default 100. The sum of limit and after cannot be more than 10000 Returns: ApiResponse: An object with the response value as well as other useful information such as status codes and headers. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/users/{accountId}/messages' _url_path = APIHelper.append_url_with_template_parameters(_url_path, { 'accountId': {'value': account_id, 'encode': False} }) _query_builder = self.config.get_base_uri(Server.MESSAGINGDEFAULT) _query_builder += _url_path _query_parameters = { 'messageId': message_id, 'sourceTn': source_tn, 'destinationTn': destination_tn, 'messageStatus': message_status, 'errorCode': error_code, 'fromDateTime': from_date_time, 'toDateTime': to_date_time, 'pageToken': page_token, 'limit': limit } _query_builder = APIHelper.append_url_with_query_parameters( _query_builder, _query_parameters ) _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json' } # Prepare and execute request _request = self.config.http_client.get(_query_url, headers=_headers) MessagingBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise MessagingException('400 Request is malformed or invalid', _response) elif _response.status_code == 401: raise MessagingException('401 The specified user does not have access to the account', _response) elif _response.status_code == 403: raise MessagingException('403 The user does not have access to this API', _response) elif _response.status_code == 404: raise MessagingException('404 Path not found', _response) elif _response.status_code == 415: raise MessagingException('415 The content-type of the request is incorrect', _response) elif _response.status_code == 429: raise MessagingException('429 The rate limit has been reached', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize(_response.text, BandwidthMessagesList.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def get_call_state(self, account_id, call_id): """Does a GET request to /api/v2/accounts/{accountId}/calls/{callId}. Returns near-realtime metadata about the specified call Args: account_id (string): TODO: type description here. call_id (string): TODO: type description here. Returns: ApiCallStateResponse: Response from the API. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/api/v2/accounts/{accountId}/calls/{callId}' _url_path = APIHelper.append_url_with_template_parameters(_url_path, { 'accountId': account_id, 'callId': call_id }) _query_builder = self.config.get_base_uri(Server.VOICEDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json' } # Prepare and execute request _request = self.config.http_client.get(_query_url, headers=_headers) VoiceBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise ApiErrorResponseException('Something\'s not quite right... Either your request is invalid or you\'re requesting it at a bad time. Please fix it before trying again.', _response) elif _response.status_code == 401: raise APIException('Please authenticate yourself.', _response) elif _response.status_code == 403: raise ApiErrorResponseException('Your credentials are invalid. Please use your API credentials for the Bandwidth Dashboard.', _response) elif _response.status_code == 404: raise ApiErrorResponseException('The resource specified cannot be found or does not belong to you.', _response) elif _response.status_code == 415: raise ApiErrorResponseException('We don\'t support that media type. If a request body is required, please send it to us as `application/json`.', _response) elif _response.status_code == 429: raise ApiErrorResponseException('You\'re sending requests to this endpoint too frequently. Please slow your request rate down and try again.', _response) elif _response.status_code == 500: raise ApiErrorResponseException('Something unexpected happened. Please try again.', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize(_response.text, ApiCallStateResponse.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def get_query_metadata_for_account(self, account_id, mfrom=None, to=None, min_start_time=None, max_start_time=None): """Does a GET request to /api/v2/accounts/{accountId}/recordings. Returns a list of metadata for the recordings associated with the specified account. The list can be filtered by the optional from, to, minStartTime, and maxStartTime arguments. The list is capped at 1000 entries and may be empty if no recordings match the specified criteria. Args: account_id (string): TODO: type description here. mfrom (string, optional): TODO: type description here. to (string, optional): TODO: type description here. min_start_time (string, optional): TODO: type description here. max_start_time (string, optional): TODO: type description here. Returns: list of RecordingMetadataResponse: Response from the API. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/api/v2/accounts/{accountId}/recordings' _url_path = APIHelper.append_url_with_template_parameters(_url_path, { 'accountId': account_id }) _query_builder = self.config.get_base_uri(Server.VOICEDEFAULT) _query_builder += _url_path _query_parameters = { 'from': mfrom, 'to': to, 'minStartTime': min_start_time, 'maxStartTime': max_start_time } _query_builder = APIHelper.append_url_with_query_parameters( _query_builder, _query_parameters ) _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json' } # Prepare and execute request _request = self.config.http_client.get(_query_url, headers=_headers) VoiceBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise ApiErrorResponseException('Something\'s not quite right... Either your request is invalid or you\'re requesting it at a bad time. Please fix it before trying again.', _response) elif _response.status_code == 401: raise APIException('Please authenticate yourself.', _response) elif _response.status_code == 403: raise ApiErrorResponseException('Your credentials are invalid. Please use your API credentials for the Bandwidth Dashboard.', _response) elif _response.status_code == 404: raise ApiErrorResponseException('The resource specified cannot be found or does not belong to you.', _response) elif _response.status_code == 415: raise ApiErrorResponseException('We don\'t support that media type. If a request body is required, please send it to us as `application/json`.', _response) elif _response.status_code == 429: raise ApiErrorResponseException('You\'re sending requests to this endpoint too frequently. Please slow your request rate down and try again.', _response) elif _response.status_code == 500: raise ApiErrorResponseException('Something unexpected happened. Please try again.', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize(_response.text, RecordingMetadataResponse.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result
def create_voice_two_factor(self, account_id, body): """Does a POST request to /accounts/{accountId}/code/voice. Multi-Factor authentication with Bandwidth Voice services. Allows for a user to send an MFA code via a phone call. Args: account_id (string): Bandwidth Account ID with Voice service enabled body (TwoFactorCodeRequestSchema): TODO: type description here. Returns: ApiResponse: An object with the response value as well as other useful information such as status codes and headers. successful operation Raises: APIException: When an error occurs while fetching the data from the remote API. This exception includes the HTTP Response code, an error message, and the HTTP body that was received in the request. """ # Prepare query URL _url_path = '/accounts/{accountId}/code/voice' _url_path = APIHelper.append_url_with_template_parameters( _url_path, {'accountId': { 'value': account_id, 'encode': False }}) _query_builder = self.config.get_base_uri( Server.MULTIFACTORAUTHDEFAULT) _query_builder += _url_path _query_url = APIHelper.clean_url(_query_builder) # Prepare headers _headers = { 'accept': 'application/json', 'content-type': 'application/json; charset=utf-8' } # Prepare and execute request _request = self.config.http_client.post( _query_url, headers=_headers, parameters=APIHelper.json_serialize(body)) MultiFactorAuthBasicAuth.apply(self.config, _request) _response = self.execute_request(_request) # Endpoint and global error handling using HTTP status codes. if _response.status_code == 400: raise ErrorWithRequestException( 'If there is any issue with values passed in by the user', _response) elif _response.status_code == 401: raise UnauthorizedRequestException( 'Authentication is either incorrect or not present', _response) elif _response.status_code == 403: raise ForbiddenRequestException( 'The user is not authorized to access this resource', _response) elif _response.status_code == 500: raise ErrorWithRequestException( 'An internal server error occurred', _response) self.validate_response(_response) decoded = APIHelper.json_deserialize( _response.text, TwoFactorVoiceResponse.from_dictionary) _result = ApiResponse(_response, body=decoded) return _result