CallFire API v1.1 Java SDK

Requirements:

Dependencies:

Project page

Getting started

Installation

Before start you should add dependency to your Java-based project. For Gradle build system add:

repositories {
    jcenter()
}
dependencies {
    compile 'com.callfire:callfire-api-1.1-client-core:X.Y.Z'
    // test dependency adds ability to create mocked CfApi11Client which doesn't send requests to production
    // but just returns mock data. See 'Testing' section for more info.
    // compile 'com.callfire:callfire-api-1.1-client-test:X.Y.Z'
}

for Maven build add following lines to your pom xml:

<!-- callfire maven repo -->
<repositories>
    <repository>
        <id>callfire-com</id>
        <name>callfire-com</name>
        <url>http://dl.bintray.com/callfire-com/maven</url>
    </repository>
</repositories>
<!-- dependency -->
<dependencies>
    <dependency>
        <groupId>com.callfire</groupId>
        <artifactId>callfire-api-1.1-client-core</artifactId>
        <version>X.Y.Z</version>
    </dependency>
<!--
    Test dependency adds ability to create mocked CfApi11Client which doesn't send requests to production
    but just returns mock data. See 'Testing' section for more info.
    <dependency>
        <groupId>com.callfire</groupId>
        <artifactId>callfire-api-1.1-client-test</artifactId>
        <version>X.Y.Z</version>
    </dependency>
-->
</dependencies>

where X.Y.Z - current available version, you can find it on releases page After these steps callfire-api-1.1-client should appear in your project dependencies along with other transitive ones.

In case you want to build it yourself:

    $ git clone https://github.com/CallFire/callfire-api-1.1-client-java.git
    $ cd callfire-api-client-java
    $ gradlew build clientFatJar

it will create 4 jars in callfire-api-1.1-client-[module name]/build/libs directory:

    core module:
    callfire-api-1.1-client-core-X.Y.Z.jar - only client classes without dependencies
    callfire-api-1.1-client-core-X.Y.Z-all.jar - client jar with all dependencies inside
    callfire-api-1.1-client-core-X.Y.Z-javadoc.jar
    callfire-api-1.1-client-core-X.Y.Z-sources.jar
    test module:
    callfire-api-1.1-client-test-X.Y.Z.jar
    callfire-api-1.1-client-test-X.Y.Z-javadoc.jar
    callfire-api-1.1-client-test-X.Y.Z-sources.jar

Overview

To create client instance just provide API login and password. API credentials should be configured on Account -> Settings -> API Access page. Client uses HTTPS connection and Basic Authentication.

Example how to send SMS to 2 recipients:

public class TestCallfireApi11 {
    public static void main(String[] args) {
        CfApi11Client client = new CfApi11Client("api_login", "api_password");
        SendTextRequest request = SendTextRequest.create()
            .name("Send Text Java API Client")
            .recipients(Arrays.asList(
                new ToNumber("12132212384"),
                new ToNumber("12132212385"))
            )
            .config(TextBroadcastConfig.create()
                .fromNumber("12132212384")
                .message("Api test message")
            )
            .build();
        Long id = client.textsApi().send(request);
        System.out.println(account);
    }
}

List of API classes:

    CfApi11Client client = new CfApi11Client("api_login", "api_password");
    client.callsApi();
    client.textsApi();
    client.subscriptionsApi();

Error handling

The CallFire Developers API uses standard HTTP response codes for responses. These HTTP codes indicate whether or not an API operation is successful.

Status Code 200 is the desired response code. A standard JSON response will follow.

Codes in the 400s range detail all of the errors a CallFire Developer could encounter while using the API. Bad Request, Rate Limit Reached, and Unauthorized are some of the sorts of responses in the 400s block.

Codes in the 500s range are error responses from the CallFire system. If an error has occurred anywhere in the execution of a resource that was not due to user input, a 500 response will be returned with a corresponding JSON error body. In that body will contain a message detailing what went wrong.

All API methods throw following exceptions (all are RuntimeException):

CfApi11ApiException has message property with details of occurred error.

Configuration

Proxy

Users have possibility to make API calls go through proxy, here is an example how to configure it:

        CfApi11Client.getClientConfig().put(ClientConstants.PROXY_ADDRESS_PROPERTY, "localhost:3128");
        CfApi11Client.getClientConfig().put(ClientConstants.PROXY_CREDENTIALS_PROPERTY, "proxyuser:proxypass");
        // now create client
        CfApi11Client client = new CfApi11Client("api_user", "api_pass");
        System.out.println("subscriptions: " + client.subscriptionsApi().query(0, 5));

IMPORTANT. You must add proxy address property and proxy credentials (if needed) before client instantiation!

Proxy address port is optional, 8080 is used by default.

Testing

Add callfire-api-1.1-client-test dependency to the project, then you can create a mocked API client which doesn't query production services, but just returns mocked data models.

Please note that testing mode is limited to return only stub data and it doesn't work like sandbox account. Lots of different validations perform on server-side thus invalid data (e.g. invalid To/From numbers, validation performs on server) will work with mock client but fails with production one.

    // create mocked client
    CfApi11Client client = MockClientFactory.newClient();
    // then run queries as usual, e.g. query
    List<Call> calls = client.callsApi().query(QueryCallsRequest.create().broadcastId(444111L).build());
Number validation

There some hardcoded values which you can use to test negative cases, e.g. when From or To number is invalid, next example shows how to send call/text to invalid number and see that number is invalid

    // create mocked client
    CfApi11Client client = MockClientFactory.newClient();
    SendCallRequest request = SendCallRequest.create()
        .name("Send Call Java API Client")
        // invalid to number
        .recipients(Collections.singletonList(new ToNumber("1234")))
        .voiceConfig(VoiceBroadcastConfig.create()
            .fromNumber("12132212384")
            .liveSound("this is LA TTS", Voice.MALE1)
            .amSound("this is AM TTS", Voice.FEMALE1)
        )
        .build();
    long id = client.callsApi().send(request);
    // response id is always 1000 for sendCall operation to number 1234
    assertEquals(1000, id);
    // then if we query this call by broadcast id it will show state as INVALID
    QueryCallsRequest queryRequest = QueryCallsRequest.create()
        .broadcastId(id)
        .build();
    List<Call> calls = client.callsApi().query(queryRequest);
    assertEquals(1, calls.size());
    assertEquals(ActionState.INVALID, calls.get(0).getState());

the same for texts

    // create mocked client
    CfApi11Client client = MockClientFactory.newClient();
    SendTextRequest request = SendTextRequest.create()
        .name("Send Text Java API Client")
        // invalid to number
        .recipients(Collections.singletonList(new ToNumber("1234")))
        .config(TextBroadcastConfig.create()
            .fromNumber("12132212384")
            .message("Api test message")
        )
        .build();
    long id = client.textsApi().send(request);
    // response id is always 2000 for sendText operation to number 1234
    assertEquals(2000, id);
    // then if we query this call by broadcast id it will show state as INVALID
    QueryTextsRequest queryRequest = QueryTextsRequest.create()
        .broadcastId(id)
        .build();
    List<Text> texts = client.textsApi().query(queryRequest);
    assertEquals(1, texts.size());
    assertEquals(ActionState.INVALID, texts.get(0).getState());

In case we sent invalid from number for sendCall/sendText operation we'll get BadRequestException

    CfApi11Client client = MockClientFactory.newClient();
    SendCallRequest request = SendCallRequest.create()
        .name("Send Call Java API Client")
        .recipients(Collections.singletonList(new ToNumber("12132212384")))
        .voiceConfig(VoiceBroadcastConfig.create()
            // invalid number
            .fromNumber("1234")
            .liveSound("this is LA TTS", Voice.MALE1)
            .amSound("this is AM TTS", Voice.FEMALE1)
        )
        .build();
    client.callsApi().send(request);
Add custom responses

In case you want to customize what mocked http client returns here is an example how to do it:

    CfApi11Client client = MockClientFactory.newClient();
    Map<String, Pair<Integer, String>> responses = CallfireTestUtils.getJsonResponseMapping(client);
    responses.put(ModelType.listOf(Subscription.class).getType().toString(), new MutablePair<>(400, "/common/errorResponse.json"));
    client.subscriptionsApi().query(0, 1);

In this case response will be taken from errorResponse.json which and BadRequestException will occur. To customize response you should:

  1. create json file with response
  2. add mapping for API operation, response code and path to your json file
    // a couple notes:
    // 1st arg is the type API operation returns, e.g. ResourceList<Subscription> for query(), Resource<Subscription>
    //  for get(), see responses of API methods
    // 2nd arg contains HTTP response code which will be returned and path to mock json file, note that base path
    //  for your file must be '/com/callfire/api11/client/api'
    responses.put(ModelType.listOf(Subscription.class).getType().toString(), new MutablePair<>(400, "/common/errorResponse.json"));
    
  3. then query API
    // response from your file will be returned
    client.subscriptionsApi().query(0, 1);
    

Debug & logging

In case you want to see requests/responses which client sends/receives from Callfire platform you should set DEBUG level for com.callfire and org.apache.http package, then you'll see something like that in your logs:

2016/05/23 21:27:07:637 EEST [DEBUG] RestApi11Client - POST request to https://www.callfire.com/api/1.1/rest/subscription.json params: [Endpoint=test_endpoint, NotificationFormat=JSON, TriggerEvent=CAMPAIGN_STARTED, BroadcastId=1, FromNumber=123, ToNumber=321]
2016/05/23 21:27:08:872 EEST [DEBUG] MainClientExec - Executing request POST /api/1.1/rest/subscription.json HTTP/1.1
2016/05/23 21:27:08:872 EEST [DEBUG] MainClientExec - Proxy auth state: UNCHALLENGED
2016/05/23 21:27:08:874 EEST [DEBUG] headers - http-outgoing-0 >> POST /api/1.1/rest/subscription.json HTTP/1.1
2016/05/23 21:27:08:874 EEST [DEBUG] headers - http-outgoing-0 >> Accept: application/json
2016/05/23 21:27:08:874 EEST [DEBUG] headers - http-outgoing-0 >> Authorization: Basic <base64-hash-goes-here>
2016/05/23 21:27:08:874 EEST [DEBUG] headers - http-outgoing-0 >> Content-Length: 118
2016/05/23 21:27:08:874 EEST [DEBUG] headers - http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1
2016/05/23 21:27:08:875 EEST [DEBUG] headers - http-outgoing-0 >> Host: www.callfire.com
2016/05/23 21:27:08:875 EEST [DEBUG] headers - http-outgoing-0 >> Connection: Keep-Alive
2016/05/23 21:27:08:875 EEST [DEBUG] headers - http-outgoing-0 >> User-Agent: callfire-api-1.1-client-java-1.0.0
2016/05/23 21:27:08:875 EEST [DEBUG] headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
2016/05/23 21:27:08:875 EEST [DEBUG] wire - http-outgoing-0 >> "POST /api/1.1/rest/subscription.json HTTP/1.1[\r][\n]"
2016/05/23 21:27:08:875 EEST [DEBUG] wire - http-outgoing-0 >> "Accept: application/json[\r][\n]"
2016/05/23 21:27:08:875 EEST [DEBUG] wire - http-outgoing-0 >> "Authorization: Basic <base64-hash-goes-here>[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "Content-Length: 118[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "Host: www.callfire.com[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "User-Agent: callfire-api-1.1-client-java-1.0.0[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "[\r][\n]"
2016/05/23 21:27:08:876 EEST [DEBUG] wire - http-outgoing-0 >> "Endpoint=test_endpoint&NotificationFormat=JSON&TriggerEvent=CAMPAIGN_STARTED&BroadcastId=1&FromNumber=123&ToNumber=321"
2016/05/23 21:27:09:109 EEST [DEBUG] wire - http-outgoing-0 << "HTTP/1.1 201 Created[\r][\n]"

If you don't have any logger implementation in classpath you can simply use commons-logging SimpleLog which are shipped with Callfire client. See example of usage below:

System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.com.callfire", "DEBUG");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "DEBUG");