All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bandwidth.voice.controllers.APIController Maven / Gradle / Ivy

Go to download

The official client SDK for Bandwidth's Voice, Messaging, MFA, and WebRTC APIs

There is a newer version: 12.0.0
Show newest version
/*
 * BandwidthLib
 *
 * This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ).
 */

package com.bandwidth.voice.controllers;

import com.bandwidth.ApiHelper;
import com.bandwidth.AuthManager;
import com.bandwidth.Configuration;
import com.bandwidth.Server;
import com.bandwidth.controllers.BaseController;
import com.bandwidth.exceptions.ApiException;
import com.bandwidth.http.Headers;
import com.bandwidth.http.client.HttpCallback;
import com.bandwidth.http.client.HttpClient;
import com.bandwidth.http.client.HttpContext;
import com.bandwidth.http.request.HttpRequest;
import com.bandwidth.http.response.ApiResponse;
import com.bandwidth.http.response.HttpResponse;
import com.bandwidth.http.response.HttpStringResponse;
import com.bandwidth.voice.exceptions.ApiErrorException;
import com.bandwidth.voice.models.CallRecordingMetadata;
import com.bandwidth.voice.models.CallState;
import com.bandwidth.voice.models.ConferenceMemberState;
import com.bandwidth.voice.models.ConferenceRecordingMetadata;
import com.bandwidth.voice.models.ConferenceState;
import com.bandwidth.voice.models.CreateCallRequest;
import com.bandwidth.voice.models.CreateCallResponse;
import com.bandwidth.voice.models.DynamicResponse;
import com.bandwidth.voice.models.ModifyCallRecordingRequest;
import com.bandwidth.voice.models.ModifyCallRequest;
import com.bandwidth.voice.models.ModifyConferenceRequest;
import com.bandwidth.voice.models.TranscribeRecordingRequest;
import com.bandwidth.voice.models.TranscriptionResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.IOException;
import java.util.AbstractMap.SimpleEntry;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * This class lists all the endpoints of the groups.
 */
public final class APIController extends BaseController {

    /**
     * Initializes the controller.
     * @param config    Configurations added in client.
     * @param httpClient    Send HTTP requests and read the responses.
     * @param authManagers    Apply authorization to requests.
     */
    public APIController(Configuration config, HttpClient httpClient,
            Map authManagers) {
        super(config, httpClient, authManagers);
    }

    /**
     * Initializes the controller with HTTPCallback.
     * @param config    Configurations added in client.
     * @param httpClient    Send HTTP requests and read the responses.
     * @param authManagers    Apply authorization to requests.
     * @param httpCallback    Callback to be called before and after the HTTP call.
     */
    public APIController(Configuration config, HttpClient httpClient,
            Map authManagers, HttpCallback httpCallback) {
        super(config, httpClient, authManagers, httpCallback);
    }

    /**
     * Creates an outbound phone call.
     * @param  accountId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the CreateCallResponse wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse createCall(
            final String accountId,
            final CreateCallRequest body) throws ApiException, IOException {
        HttpRequest request = buildCreateCallRequest(accountId, body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleCreateCallResponse(context);
    }

    /**
     * Creates an outbound phone call.
     * @param  accountId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the CreateCallResponse wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> createCallAsync(
            final String accountId,
            final CreateCallRequest body) {
        return makeHttpCallAsync(() -> buildCreateCallRequest(accountId, body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleCreateCallResponse(context));
    }

    /**
     * Builds the HttpRequest object for createCall.
     */
    private HttpRequest buildCreateCallRequest(
            final String accountId,
            final CreateCallRequest body) throws JsonProcessingException {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");
        headers.add("content-type", "application/json");

        //prepare and invoke the API call request to fetch the response
        String bodyJson = ApiHelper.serialize(body);
        HttpRequest request = getClientInstance().postBody(queryBuilder, headers, null, bodyJson);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for createCall.
     * @return An object of type CreateCallResponse
     */
    private ApiResponse handleCreateCallResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        CreateCallResponse result = ApiHelper.deserialize(responseBody,
                CreateCallResponse.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Returns near-realtime metadata about the specified call.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @return    Returns the CallState wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getCall(
            final String accountId,
            final String callId) throws ApiException, IOException {
        HttpRequest request = buildGetCallRequest(accountId, callId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetCallResponse(context);
    }

    /**
     * Returns near-realtime metadata about the specified call.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @return    Returns the CallState wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getCallAsync(
            final String accountId,
            final String callId) {
        return makeHttpCallAsync(() -> buildGetCallRequest(accountId, callId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetCallResponse(context));
    }

    /**
     * Builds the HttpRequest object for getCall.
     */
    private HttpRequest buildGetCallRequest(
            final String accountId,
            final String callId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getCall.
     * @return An object of type CallState
     */
    private ApiResponse handleGetCallResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        CallState result = ApiHelper.deserialize(responseBody,
                CallState.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Interrupts and replaces an active call's BXML document.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse modifyCall(
            final String accountId,
            final String callId,
            final ModifyCallRequest body) throws ApiException, IOException {
        HttpRequest request = buildModifyCallRequest(accountId, callId, body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleModifyCallResponse(context);
    }

    /**
     * Interrupts and replaces an active call's BXML document.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> modifyCallAsync(
            final String accountId,
            final String callId,
            final ModifyCallRequest body) {
        return makeHttpCallAsync(() -> buildModifyCallRequest(accountId, callId, body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleModifyCallResponse(context));
    }

    /**
     * Builds the HttpRequest object for modifyCall.
     */
    private HttpRequest buildModifyCallRequest(
            final String accountId,
            final String callId,
            final ModifyCallRequest body) throws JsonProcessingException {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("content-type", "application/json");

        //prepare and invoke the API call request to fetch the response
        String bodyJson = ApiHelper.serialize(body);
        HttpRequest request = getClientInstance().postBody(queryBuilder, headers, null, bodyJson);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for modifyCall.
     * @return An object of type void
     */
    private ApiResponse handleModifyCallResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

/**
     * Interrupts and replaces an active call's BXML document.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example: Needs to be a valid xml string
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse modifyCallBxml(
            final String accountId,
            final String callId,
            final String body) throws ApiException, IOException {
        HttpRequest request = buildModifyCallBxmlRequest(accountId, callId, body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleModifyCallBxmlResponse(context);
    }

    /**
     * Interrupts and replaces an active call's BXML document.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example: valid xml string
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> modifyCallBxmlAsync(
            final String accountId,
            final String callId,
            final String body) {
        return makeHttpCallAsync(() -> buildModifyCallBxmlRequest(accountId, callId, body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleModifyCallBxmlResponse(context));
    }

    /**
     * Builds the HttpRequest object for modifyCallBxml.
     */
    private HttpRequest buildModifyCallBxmlRequest(
            final String accountId,
            final String callId,
            final String body) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/bxml");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("content-type", "application/xml");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().putBody(queryBuilder, headers, null, body);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for modifyCallBxml.
     * @return An object of type void
     */
    private ApiResponse handleModifyCallBxmlResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/xml`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }


    /**
     * Pauses or resumes a recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse modifyCallRecordingState(
            final String accountId,
            final String callId,
            final ModifyCallRecordingRequest body) throws ApiException, IOException {
        HttpRequest request = buildModifyCallRecordingStateRequest(accountId, callId, body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleModifyCallRecordingStateResponse(context);
    }

    /**
     * Pauses or resumes a recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> modifyCallRecordingStateAsync(
            final String accountId,
            final String callId,
            final ModifyCallRecordingRequest body) {
        return makeHttpCallAsync(() -> buildModifyCallRecordingStateRequest(accountId, callId,
                body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleModifyCallRecordingStateResponse(context));
    }

    /**
     * Builds the HttpRequest object for modifyCallRecordingState.
     */
    private HttpRequest buildModifyCallRecordingStateRequest(
            final String accountId,
            final String callId,
            final ModifyCallRecordingRequest body) throws JsonProcessingException {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recording");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("content-type", "application/json");

        //prepare and invoke the API call request to fetch the response
        String bodyJson = ApiHelper.serialize(body);
        HttpRequest request = getClientInstance().putBody(queryBuilder, headers, null, bodyJson);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for modifyCallRecordingState.
     * @return An object of type void
     */
    private ApiResponse handleModifyCallRecordingStateResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Returns a (potentially empty) list of metadata for the recordings that took place during the
     * specified call.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @return    Returns the List of CallRecordingMetadata wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse> getCallRecordings(
            final String accountId,
            final String callId) throws ApiException, IOException {
        HttpRequest request = buildGetCallRecordingsRequest(accountId, callId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetCallRecordingsResponse(context);
    }

    /**
     * Returns a (potentially empty) list of metadata for the recordings that took place during the
     * specified call.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @return    Returns the List of CallRecordingMetadata wrapped in ApiResponse response from the API call
     */
    public CompletableFuture>> getCallRecordingsAsync(
            final String accountId,
            final String callId) {
        return makeHttpCallAsync(() -> buildGetCallRecordingsRequest(accountId, callId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetCallRecordingsResponse(context));
    }

    /**
     * Builds the HttpRequest object for getCallRecordings.
     */
    private HttpRequest buildGetCallRecordingsRequest(
            final String accountId,
            final String callId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getCallRecordings.
     * @return An object of type List of CallRecordingMetadata
     */
    private ApiResponse> handleGetCallRecordingsResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        List result = ApiHelper.deserializeArray(responseBody,
                CallRecordingMetadata[].class);
        return new ApiResponse>(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Returns metadata for the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the CallRecordingMetadata wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getCallRecording(
            final String accountId,
            final String callId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildGetCallRecordingRequest(accountId, callId, recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetCallRecordingResponse(context);
    }

    /**
     * Returns metadata for the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the CallRecordingMetadata wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getCallRecordingAsync(
            final String accountId,
            final String callId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildGetCallRecordingRequest(accountId, callId, recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, true)),
            context -> handleGetCallRecordingResponse(context));
    }

    /**
     * Builds the HttpRequest object for getCallRecording.
     */
    private HttpRequest buildGetCallRecordingRequest(
            final String accountId,
            final String callId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getCallRecording.
     * @return An object of type CallRecordingMetadata
     */
    private ApiResponse handleGetCallRecordingResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        CallRecordingMetadata result = ApiHelper.deserialize(responseBody,
                CallRecordingMetadata.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Deletes the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse deleteRecording(
            final String accountId,
            final String callId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildDeleteRecordingRequest(accountId, callId, recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleDeleteRecordingResponse(context);
    }

    /**
     * Deletes the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> deleteRecordingAsync(
            final String accountId,
            final String callId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildDeleteRecordingRequest(accountId, callId, recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleDeleteRecordingResponse(context));
    }

    /**
     * Builds the HttpRequest object for deleteRecording.
     */
    private HttpRequest buildDeleteRecordingRequest(
            final String accountId,
            final String callId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().delete(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for deleteRecording.
     * @return An object of type void
     */
    private ApiResponse handleDeleteRecordingResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Downloads the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the DynamicResponse wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getDownloadCallRecording(
            final String accountId,
            final String callId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildGetDownloadCallRecordingRequest(accountId, callId, recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, true);
        HttpContext context = new HttpContext(request, response);

        return handleGetDownloadCallRecordingResponse(context);
    }

    /**
     * Downloads the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the DynamicResponse wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getDownloadCallRecordingAsync(
            final String accountId,
            final String callId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildGetDownloadCallRecordingRequest(accountId, callId,
                recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, true)),
            context -> handleGetDownloadCallRecordingResponse(context));
    }

    /**
     * Builds the HttpRequest object for getDownloadCallRecording.
     */
    private HttpRequest buildGetDownloadCallRecordingRequest(
            final String accountId,
            final String callId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/media");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getDownloadCallRecording.
     * @return An object of type DynamicResponse
     */
    private ApiResponse handleGetDownloadCallRecordingResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        DynamicResponse result = new DynamicResponse(response);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Deletes the specified recording's media.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse deleteRecordingMedia(
            final String accountId,
            final String callId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildDeleteRecordingMediaRequest(accountId, callId, recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleDeleteRecordingMediaResponse(context);
    }

    /**
     * Deletes the specified recording's media.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> deleteRecordingMediaAsync(
            final String accountId,
            final String callId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildDeleteRecordingMediaRequest(accountId, callId,
                recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleDeleteRecordingMediaResponse(context));
    }

    /**
     * Builds the HttpRequest object for deleteRecordingMedia.
     */
    private HttpRequest buildDeleteRecordingMediaRequest(
            final String accountId,
            final String callId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/media");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().delete(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for deleteRecordingMedia.
     * @return An object of type void
     */
    private ApiResponse handleDeleteRecordingMediaResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Downloads the specified transcription.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the TranscriptionResponse wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getCallTranscription(
            final String accountId,
            final String callId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildGetCallTranscriptionRequest(accountId, callId, recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetCallTranscriptionResponse(context);
    }

    /**
     * Downloads the specified transcription.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the TranscriptionResponse wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getCallTranscriptionAsync(
            final String accountId,
            final String callId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildGetCallTranscriptionRequest(accountId, callId,
                recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetCallTranscriptionResponse(context));
    }

    /**
     * Builds the HttpRequest object for getCallTranscription.
     */
    private HttpRequest buildGetCallTranscriptionRequest(
            final String accountId,
            final String callId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/transcription");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getCallTranscription.
     * @return An object of type TranscriptionResponse
     */
    private ApiResponse handleGetCallTranscriptionResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        TranscriptionResponse result = ApiHelper.deserialize(responseBody,
                TranscriptionResponse.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Requests that the specified recording be transcribed.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse createTranscribeCallRecording(
            final String accountId,
            final String callId,
            final String recordingId,
            final TranscribeRecordingRequest body) throws ApiException, IOException {
        HttpRequest request = buildCreateTranscribeCallRecordingRequest(accountId, callId,
                recordingId, body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleCreateTranscribeCallRecordingResponse(context);
    }

    /**
     * Requests that the specified recording be transcribed.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> createTranscribeCallRecordingAsync(
            final String accountId,
            final String callId,
            final String recordingId,
            final TranscribeRecordingRequest body) {
        return makeHttpCallAsync(() -> buildCreateTranscribeCallRecordingRequest(accountId, callId,
                recordingId, body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleCreateTranscribeCallRecordingResponse(context));
    }

    /**
     * Builds the HttpRequest object for createTranscribeCallRecording.
     */
    private HttpRequest buildCreateTranscribeCallRecordingRequest(
            final String accountId,
            final String callId,
            final String recordingId,
            final TranscribeRecordingRequest body) throws JsonProcessingException {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/transcription");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("content-type", "application/json");

        //prepare and invoke the API call request to fetch the response
        String bodyJson = ApiHelper.serialize(body);
        HttpRequest request = getClientInstance().postBody(queryBuilder, headers, null, bodyJson);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for createTranscribeCallRecording.
     * @return An object of type void
     */
    private ApiResponse handleCreateTranscribeCallRecordingResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 410) {
            throw new ApiErrorException(
                    "The media for this recording has been deleted, so we can't transcribe it",
                    context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Deletes the specified recording's transcription.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse deleteCallTranscription(
            final String accountId,
            final String callId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildDeleteCallTranscriptionRequest(accountId, callId, recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleDeleteCallTranscriptionResponse(context);
    }

    /**
     * Deletes the specified recording's transcription.
     * @param  accountId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> deleteCallTranscriptionAsync(
            final String accountId,
            final String callId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildDeleteCallTranscriptionRequest(accountId, callId,
                recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleDeleteCallTranscriptionResponse(context));
    }

    /**
     * Builds the HttpRequest object for deleteCallTranscription.
     */
    private HttpRequest buildDeleteCallTranscriptionRequest(
            final String accountId,
            final String callId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/transcription");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().delete(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for deleteCallTranscription.
     * @return An object of type void
     */
    private ApiResponse handleDeleteCallTranscriptionResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Returns information about the conferences in the account.
     * @param  accountId  Required parameter: Example:
     * @param  name  Optional parameter: Example:
     * @param  minCreatedTime  Optional parameter: Example:
     * @param  maxCreatedTime  Optional parameter: Example:
     * @param  pageSize  Optional parameter: Example: 1000
     * @param  pageToken  Optional parameter: Example:
     * @return    Returns the List of ConferenceState wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse> getConferences(
            final String accountId,
            final String name,
            final String minCreatedTime,
            final String maxCreatedTime,
            final Integer pageSize,
            final String pageToken) throws ApiException, IOException {
        HttpRequest request = buildGetConferencesRequest(accountId, name, minCreatedTime,
                maxCreatedTime, pageSize, pageToken);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetConferencesResponse(context);
    }

    /**
     * Returns information about the conferences in the account.
     * @param  accountId  Required parameter: Example:
     * @param  name  Optional parameter: Example:
     * @param  minCreatedTime  Optional parameter: Example:
     * @param  maxCreatedTime  Optional parameter: Example:
     * @param  pageSize  Optional parameter: Example: 1000
     * @param  pageToken  Optional parameter: Example:
     * @return    Returns the List of ConferenceState wrapped in ApiResponse response from the API call
     */
    public CompletableFuture>> getConferencesAsync(
            final String accountId,
            final String name,
            final String minCreatedTime,
            final String maxCreatedTime,
            final Integer pageSize,
            final String pageToken) {
        return makeHttpCallAsync(() -> buildGetConferencesRequest(accountId, name, minCreatedTime,
                maxCreatedTime, pageSize, pageToken),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetConferencesResponse(context));
    }

    /**
     * Builds the HttpRequest object for getConferences.
     */
    private HttpRequest buildGetConferencesRequest(
            final String accountId,
            final String name,
            final String minCreatedTime,
            final String maxCreatedTime,
            final Integer pageSize,
            final String pageToken) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all query parameters
        Map queryParameters = new HashMap<>();
        queryParameters.put("name", name);
        queryParameters.put("minCreatedTime", minCreatedTime);
        queryParameters.put("maxCreatedTime", maxCreatedTime);
        queryParameters.put("pageSize",
                (pageSize != null) ? pageSize : 1000);
        queryParameters.put("pageToken", pageToken);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, queryParameters,
                null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getConferences.
     * @return An object of type List of ConferenceState
     */
    private ApiResponse> handleGetConferencesResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        List result = ApiHelper.deserializeArray(responseBody,
                ConferenceState[].class);
        return new ApiResponse>(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Returns information about the specified conference.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @return    Returns the ConferenceState wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getConference(
            final String accountId,
            final String conferenceId) throws ApiException, IOException {
        HttpRequest request = buildGetConferenceRequest(accountId, conferenceId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetConferenceResponse(context);
    }

    /**
     * Returns information about the specified conference.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @return    Returns the ConferenceState wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getConferenceAsync(
            final String accountId,
            final String conferenceId) {
        return makeHttpCallAsync(() -> buildGetConferenceRequest(accountId, conferenceId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetConferenceResponse(context));
    }

    /**
     * Builds the HttpRequest object for getConference.
     */
    private HttpRequest buildGetConferenceRequest(
            final String accountId,
            final String conferenceId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getConference.
     * @return An object of type ConferenceState
     */
    private ApiResponse handleGetConferenceResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        ConferenceState result = ApiHelper.deserialize(responseBody,
                ConferenceState.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Modify the conference state.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse modifyConference(
            final String accountId,
            final String conferenceId,
            final ModifyConferenceRequest body) throws ApiException, IOException {
        HttpRequest request = buildModifyConferenceRequest(accountId, conferenceId, body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleModifyConferenceResponse(context);
    }

    /**
     * Modify the conference state.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> modifyConferenceAsync(
            final String accountId,
            final String conferenceId,
            final ModifyConferenceRequest body) {
        return makeHttpCallAsync(() -> buildModifyConferenceRequest(accountId, conferenceId, body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleModifyConferenceResponse(context));
    }

    /**
     * Builds the HttpRequest object for modifyConference.
     */
    private HttpRequest buildModifyConferenceRequest(
            final String accountId,
            final String conferenceId,
            final ModifyConferenceRequest body) throws JsonProcessingException {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("content-type", "application/json");

        //prepare and invoke the API call request to fetch the response
        String bodyJson = ApiHelper.serialize(body);
        HttpRequest request = getClientInstance().postBody(queryBuilder, headers, null, bodyJson);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for modifyConference.
     * @return An object of type void
     */
    private ApiResponse handleModifyConferenceResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Updates settings for a particular conference member.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse modifyConferenceMember(
            final String accountId,
            final String conferenceId,
            final String callId,
            final ConferenceMemberState body) throws ApiException, IOException {
        HttpRequest request = buildModifyConferenceMemberRequest(accountId, conferenceId, callId,
                body);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleModifyConferenceMemberResponse(context);
    }

    /**
     * Updates settings for a particular conference member.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  callId  Required parameter: Example:
     * @param  body  Required parameter: Example:
     * @return    Returns the Void wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> modifyConferenceMemberAsync(
            final String accountId,
            final String conferenceId,
            final String callId,
            final ConferenceMemberState body) {
        return makeHttpCallAsync(() -> buildModifyConferenceMemberRequest(accountId, conferenceId,
                callId, body),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleModifyConferenceMemberResponse(context));
    }

    /**
     * Builds the HttpRequest object for modifyConferenceMember.
     */
    private HttpRequest buildModifyConferenceMemberRequest(
            final String accountId,
            final String conferenceId,
            final String callId,
            final ConferenceMemberState body) throws JsonProcessingException {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}/members/{callId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        templateParameters.put("callId",
                new SimpleEntry(callId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("content-type", "application/json");

        //prepare and invoke the API call request to fetch the response
        String bodyJson = ApiHelper.serialize(body);
        HttpRequest request = getClientInstance().putBody(queryBuilder, headers, null, bodyJson);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for modifyConferenceMember.
     * @return An object of type void
     */
    private ApiResponse handleModifyConferenceMemberResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), null);
    }

    /**
     * Returns information about the specified conference member.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  memberId  Required parameter: Example:
     * @return    Returns the ConferenceMemberState wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getConferenceMember(
            final String accountId,
            final String conferenceId,
            final String memberId) throws ApiException, IOException {
        HttpRequest request = buildGetConferenceMemberRequest(accountId, conferenceId, memberId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetConferenceMemberResponse(context);
    }

    /**
     * Returns information about the specified conference member.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  memberId  Required parameter: Example:
     * @return    Returns the ConferenceMemberState wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getConferenceMemberAsync(
            final String accountId,
            final String conferenceId,
            final String memberId) {
        return makeHttpCallAsync(() -> buildGetConferenceMemberRequest(accountId, conferenceId,
                memberId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetConferenceMemberResponse(context));
    }

    /**
     * Builds the HttpRequest object for getConferenceMember.
     */
    private HttpRequest buildGetConferenceMemberRequest(
            final String accountId,
            final String conferenceId,
            final String memberId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}/members/{memberId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        templateParameters.put("memberId",
                new SimpleEntry(memberId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getConferenceMember.
     * @return An object of type ConferenceMemberState
     */
    private ApiResponse handleGetConferenceMemberResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        ConferenceMemberState result = ApiHelper.deserialize(responseBody,
                ConferenceMemberState.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Returns a (potentially empty) list of metadata for the recordings that took place during the
     * specified conference.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @return    Returns the List of ConferenceRecordingMetadata wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse> getConferenceRecordings(
            final String accountId,
            final String conferenceId) throws ApiException, IOException {
        HttpRequest request = buildGetConferenceRecordingsRequest(accountId, conferenceId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetConferenceRecordingsResponse(context);
    }

    /**
     * Returns a (potentially empty) list of metadata for the recordings that took place during the
     * specified conference.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @return    Returns the List of ConferenceRecordingMetadata wrapped in ApiResponse response from the API call
     */
    public CompletableFuture>> getConferenceRecordingsAsync(
            final String accountId,
            final String conferenceId) {
        return makeHttpCallAsync(() -> buildGetConferenceRecordingsRequest(accountId, conferenceId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetConferenceRecordingsResponse(context));
    }

    /**
     * Builds the HttpRequest object for getConferenceRecordings.
     */
    private HttpRequest buildGetConferenceRecordingsRequest(
            final String accountId,
            final String conferenceId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}/recordings");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getConferenceRecordings.
     * @return An object of type List of ConferenceRecordingMetadata
     */
    private ApiResponse> handleGetConferenceRecordingsResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        List result = ApiHelper.deserializeArray(responseBody,
                ConferenceRecordingMetadata[].class);
        return new ApiResponse>(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Returns metadata for the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the CallRecordingMetadata wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getConferenceRecording(
            final String accountId,
            final String conferenceId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildGetConferenceRecordingRequest(accountId, conferenceId,
                recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetConferenceRecordingResponse(context);
    }

    /**
     * Returns metadata for the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the CallRecordingMetadata wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getConferenceRecordingAsync(
            final String accountId,
            final String conferenceId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildGetConferenceRecordingRequest(accountId, conferenceId,
                recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetConferenceRecordingResponse(context));
    }

    /**
     * Builds the HttpRequest object for getConferenceRecording.
     */
    private HttpRequest buildGetConferenceRecordingRequest(
            final String accountId,
            final String conferenceId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}/recordings/{recordingId}");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getConferenceRecording.
     * @return An object of type CallRecordingMetadata
     */
    private ApiResponse handleGetConferenceRecordingResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        CallRecordingMetadata result = ApiHelper.deserialize(responseBody,
                CallRecordingMetadata.class);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * Downloads the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the DynamicResponse wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse getDownloadConferenceRecording(
            final String accountId,
            final String conferenceId,
            final String recordingId) throws ApiException, IOException {
        HttpRequest request = buildGetDownloadConferenceRecordingRequest(accountId, conferenceId,
                recordingId);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetDownloadConferenceRecordingResponse(context);
    }

    /**
     * Downloads the specified recording.
     * @param  accountId  Required parameter: Example:
     * @param  conferenceId  Required parameter: Example:
     * @param  recordingId  Required parameter: Example:
     * @return    Returns the DynamicResponse wrapped in ApiResponse response from the API call
     */
    public CompletableFuture> getDownloadConferenceRecordingAsync(
            final String accountId,
            final String conferenceId,
            final String recordingId) {
        return makeHttpCallAsync(() -> buildGetDownloadConferenceRecordingRequest(accountId,
                conferenceId, recordingId),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetDownloadConferenceRecordingResponse(context));
    }

    /**
     * Builds the HttpRequest object for getDownloadConferenceRecording.
     */
    private HttpRequest buildGetDownloadConferenceRecordingRequest(
            final String accountId,
            final String conferenceId,
            final String recordingId) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/conferences/{conferenceId}/recordings/{recordingId}/media");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        templateParameters.put("conferenceId",
                new SimpleEntry(conferenceId, false));
        templateParameters.put("recordingId",
                new SimpleEntry(recordingId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, null, null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getDownloadConferenceRecording.
     * @return An object of type DynamicResponse
     */
    private ApiResponse handleGetDownloadConferenceRecordingResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        DynamicResponse result = new DynamicResponse(response);

        return new ApiResponse(response.getStatusCode(), response.getHeaders(), result);
    }

    /**
     * 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.
     * @param  accountId  Required parameter: Example:
     * @param  from  Optional parameter: Example:
     * @param  to  Optional parameter: Example:
     * @param  minStartTime  Optional parameter: Example:
     * @param  maxStartTime  Optional parameter: Example:
     * @return    Returns the List of CallRecordingMetadata wrapped in ApiResponse response from the API call
     * @throws    ApiException    Represents error response from the server.
     * @throws    IOException    Signals that an I/O exception of some sort has occurred.
     */
    public ApiResponse> getQueryCallRecordings(
            final String accountId,
            final String from,
            final String to,
            final String minStartTime,
            final String maxStartTime) throws ApiException, IOException {
        HttpRequest request = buildGetQueryCallRecordingsRequest(accountId, from, to, minStartTime,
                maxStartTime);
        authManagers.get("voice").apply(request);

        HttpResponse response = getClientInstance().execute(request, false);
        HttpContext context = new HttpContext(request, response);

        return handleGetQueryCallRecordingsResponse(context);
    }

    /**
     * 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.
     * @param  accountId  Required parameter: Example:
     * @param  from  Optional parameter: Example:
     * @param  to  Optional parameter: Example:
     * @param  minStartTime  Optional parameter: Example:
     * @param  maxStartTime  Optional parameter: Example:
     * @return    Returns the List of CallRecordingMetadata wrapped in ApiResponse response from the API call
     */
    public CompletableFuture>> getQueryCallRecordingsAsync(
            final String accountId,
            final String from,
            final String to,
            final String minStartTime,
            final String maxStartTime) {
        return makeHttpCallAsync(() -> buildGetQueryCallRecordingsRequest(accountId, from, to,
                minStartTime, maxStartTime),
            req -> authManagers.get("voice").applyAsync(req)
                .thenCompose(request -> getClientInstance()
                        .executeAsync(request, false)),
            context -> handleGetQueryCallRecordingsResponse(context));
    }

    /**
     * Builds the HttpRequest object for getQueryCallRecordings.
     */
    private HttpRequest buildGetQueryCallRecordingsRequest(
            final String accountId,
            final String from,
            final String to,
            final String minStartTime,
            final String maxStartTime) {
        //the base uri for api requests
        String baseUri = config.getBaseUri(Server.VOICEDEFAULT);

        //prepare query string for API call
        final StringBuilder queryBuilder = new StringBuilder(baseUri
                + "/api/v2/accounts/{accountId}/recordings");

        //process template parameters
        Map> templateParameters = new HashMap<>();
        templateParameters.put("accountId",
                new SimpleEntry(accountId, false));
        ApiHelper.appendUrlWithTemplateParameters(queryBuilder, templateParameters);

        //load all query parameters
        Map queryParameters = new HashMap<>();
        queryParameters.put("from", from);
        queryParameters.put("to", to);
        queryParameters.put("minStartTime", minStartTime);
        queryParameters.put("maxStartTime", maxStartTime);

        //load all headers for the outgoing API request
        Headers headers = new Headers();
        headers.add("user-agent", BaseController.userAgent);
        headers.add("accept", "application/json");

        //prepare and invoke the API call request to fetch the response
        HttpRequest request = getClientInstance().get(queryBuilder, headers, queryParameters,
                null);

        // Invoke the callback before request if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onBeforeRequest(request);
        }

        return request;
    }

    /**
     * Processes the response for getQueryCallRecordings.
     * @return An object of type List of CallRecordingMetadata
     */
    private ApiResponse> handleGetQueryCallRecordingsResponse(
            HttpContext context) throws ApiException, IOException {
        HttpResponse response = context.getResponse();

        //invoke the callback after response if its not null
        if (getHttpCallback() != null) {
            getHttpCallback().onAfterResponse(context);
        }

        //Error handling using HTTP status codes
        int responseCode = response.getStatusCode();

        if (responseCode == 400) {
            throw new ApiErrorException(
                    "Something's not quite right... Your request is invalid. Please fix it before trying again.",
                    context);
        }
        if (responseCode == 401) {
            throw new ApiException(
                    "Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.",
                    context);
        }
        if (responseCode == 403) {
            throw new ApiErrorException("User unauthorized to perform this action.", context);
        }
        if (responseCode == 404) {
            throw new ApiErrorException(
                    "The resource specified cannot be found or does not belong to you.", context);
        }
        if (responseCode == 415) {
            throw new ApiErrorException(
                    "We don't support that media type. If a request body is required, please send it to us as `application/json`.",
                    context);
        }
        if (responseCode == 429) {
            throw new ApiErrorException(
                    "You're sending requests to this endpoint too frequently. Please slow your request rate down and try again.",
                    context);
        }
        if (responseCode == 500) {
            throw new ApiErrorException("Something unexpected happened. Please try again.",
                    context);
        }
        //handle errors defined at the API level
        validateResponse(response, context);

        //extract result from the http response
        String responseBody = ((HttpStringResponse) response).getBody();
        List result = ApiHelper.deserializeArray(responseBody,
                CallRecordingMetadata[].class);
        return new ApiResponse>(response.getStatusCode(), response.getHeaders(), result);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy