Java SDK for ContactHub
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Contacthub Java SDK

Build Status Latest tag

Adding this library to your project dependencies


In your build.sbt:

libraryDependencies += "it.contactlab.hub" % "sdk-java" % "1.2.1"


In your build.gradle:

dependencies {
  compile 'it.contactlab.hub:sdk-java:1.2.1


In your pom.xml:


Importing this library into your project


We also provide a separate async implementation where all the methods return a Java8 CompletionStage<T>.

If you wish the use the Async API, import from the async package instead:


All the following methods are available in both packages.


Find your token, workspaceId and nodeId in the Contacthub UI. Then instantiate a new Contacthub object as follows:

Auth auth = new Auth(token, workspaceId, nodeId);

ContactHub ch = new ContactHub(auth);

Custom API url

If you want to use a non-standard baseUrl for the API (for example to connect to a staging environment), you can add the API base URL as an optional parameter:

Auth auth = new Auth(token, workspaceId, nodeId, apiUrl);

If not specified, the SDK will use the default URL for the Contacthub API:


When the API returns a paginated set of results, the SDK will return an instance of Paginated<T>. This class has the following methods:

  • elements(): returns a List<T> containing the elements of the current page
  • page(): returns an instance of Page containing some page metadata (current page number, total number of pages, etc.)
  • nextPage(): sends a new API request and returns a new instance of Paginated<T> for the next page
  • previousPage(): sends a new API request and returns a new instance of Paginated<T> for the previous page

nextPage() and previousPage wrap the result in an Optional. If you try to call nextPage() when you have reached the last page, or previousPage() from the first page, you will get an empty Optional instance.

Session API


Generate a new sessionId.

String sessionId = ch.createSessionId();


Reconcile a sessionId with an existing Customer. Use this if you want to associate anonymous events (containing a sessionId) with an existing customerId.

ch.addCustomerSession(customerId, sessionId);

Customer API


Retrieve a customer by their ID.

Customer customer = ch.getCustomer("a-valid-customer-id");


Retrieve all the Customers in a node.

Paginated<Customer> customers = ch.getCustomers();

This method returns an instance of Paginated<T>. See Pagination.

getCustomers with extra options

Paginated<Customer> customers = ch.getCustomers(options);

options is an instance of GetCustomersOptions, which can contain one or more of the following attributes:

  • externalId: filters Customers by externalId
  • fields: a whitelist of Customer properties you are interested in
  • query: a QueryContainer (see Custom Queries).
  • sort: the field to order the results by
  • direction: the order of the sorting (asc or desc)
  • page: the page to retrieve (defaults to 0)

This method returns an instance of Paginated<T>. See Pagination.


Retrieve all the Customers matching a specific external ID.

Paginated<Customer> customers = ch.getCustomerByExternalId("an-external-id");

This method will return the same result you would get from this more verbose request:

Paginated<Customer> customers = ch.getCustomers(

Please note you can have more than one customer with the same external ID, unless you include "external ID" in the "matching policies" for your workspace.

This method returns an instance of Paginated<T>. See Pagination.


Add a new Customer. This method returns a new Customer object including the ID that was assigned to the new customer by the API.

Customer newCustomer = ch.addCustomer(customer)

If the "Customer uniqueness" configuration for your workspace is set to "Merge" and the new customer data matches an existing customer according to the "matching policies", this method will return the merged Customer data.

To create a Customer instance that this method requires as its argument, use the builder provided by the Customer object.

        // ...


Delete the Customer with the specified ID.



Update an existing Customer by replacing all of their data with the data provided.

Customer updatedCustomer = ch.updateCustomer(newCustomer);

This method will fail if the ID of the newCustomer does not match an existing customer.


Update an existing Customer (identified by id) by merging their existing data with the data provided.

Customer updatedCustomer = ch.patchCustomer(String id, Customer modifiedCustomer);

Customer properties that were already set and are included in the new data, will be overwritten.

Customer properties that were already set, but are not included, will be left untouched.

For example, if you want to update the email of a customer and nothing else, you can use:

Customer patchCustomer = Customer.builder()

Customer updatedCustomer = ch.patchCustomer(customerId, patchCustomer);

How to use the Customer class

When you create a new Customer, you have to set at least one between base, extended and externalId using Customer.builder(). Nested objects must be created with their own builder() methods. Most properties are optional.

When you read a Customer from the API, you get an immutable instance of Customer with a few additional properties:

  • an id
  • a registedAt property
  • an updatedAt property

All optional properties are wrapped in an Optional<T> to statically check you cannot run into a NullPointerException.

To update a Customer, you need to retrieve it and create a modified immutable copy using the withX() methods (e.g. withExternalId()).

To patch a Customer, you create a "patch" instance with the same Customer.builder() you use to create a new Customer, but you set only the fields you want to patch. All the fields that are not explicitly set in the "patch" object will be left untouched.

Further details about the Customer class can be found in Contactlab Developer Site schemas documentation: or in the Javadoc of this project:

Education API

The following methods are useful ways to add/update/remove the Education objects of a Customer.


Customer updatedCustomer = ch.addEducation(customerId, education);


Customer updatedCustomer = ch.updateEducation(customerId, education);


Customer updatedCustomer = ch.removeEducation(customerId, educationId);

Like API

The following methods are useful ways to add/update/remove the Like objects of a Customer.


Customer updatedCustomer = ch.addLike(customerId, like);


Customer updatedCustomer = ch.updateLike(customerId, like);


Customer updatedCustomer = ch.removeLike(customerId, likeId);


The following methods are useful ways to add/update/remove the Job objects of a Customer.


Customer updatedCustomer = ch.addJob(customerId, Job job);


Customer updatedCustomer = ch.updateJob(customerId, Job job);


Customer updatedCustomer = ch.removeJob(customerId, String jobId);



Add a tag to a Customer. If the tag is already present, nothing is changed.

Customer updatedCustomer = ch.addTag(customerId, "a-new-tag");


Remove a tag from a Customer. If the tag is already present, nothing is changed.

Customer updatedCustomer = ch.addTag(customerId, "a-tag-to-remove");

Custom Queries

Advanced searches and filtering of Customers can be performed using Custom Queries.


A Custom Query is an instance of QueryContainer that can be generated in two ways:

Basic custom queries

QueryContainer customQuery = ch.createQuery(
    "base.firstName", Operator.EQUALS, "Mario"
QueryContainer customQuery = ch.createQuery(
    "base.pictureUrl", Operator.IS_NOT_NULL)

Advanced custom queries

The SDK lets you use the full power of the ContactHub API query language. The SDK methods closely mirror the structure of the API query format. Refer to the API documentation for more details.

QueryContainer customQuery = QueryContainer.builder()
  .name("An optional name for your query")

Event API


Retrieve an event using its ID.

Event event = ch.getEvent("a-valid-event-id");


Retrieve all the events for a customer.

Paginated<Event> events = ch.getEvents(customerId);

This method returns an instance of Paginated<T>. See Pagination.


To create an Event instance, use the builder provided by one the Event subtypes object. Currently there are 9 Event subtypes, that are characterized by their context: they are ContactCenterEvent,DigitalCampaignEvent,EcommerceEvent,IotEvent,MobileEvent,OtherEvent, RetailEvent,SocialEvent and WebEvent.

event = WebEvent.builder()

As Event subtypes are characterized by their context, you should not specify it in the builder. The type of eventProperties must be a subtype of AbstractContextInfo, and each Event subtype specifies its AbstractContextInfo subtype. Please check the Javadoc at if you need further information. When your event is built, you can add it using the following method:

queued = ch.addEvent(event)

The API will process the event queue asynchronously, and it can take a few seconds for an event to be actually stored.


This will generate a valid eventProperties object for a viewedPage event:

HashMap<String, Object> eventProperties = new HashMap<String, Object>();
eventProperties.put("url", "");
eventProperties.put("title", "Page Title");


See the example folder for working examples that you can download and try out.

Contributing to this library

Although this is a Java library, we use sbt as the build tool.

sbt compile will compile all the Java sources to target/classes.

sbt package will package the compiled files in a JAR file under target.

sbt doc will generate an HTML JavaDoc in target/api.

sbt packageDoc will package the javadoc files in a JAR file under target.

sbt test will run the tests. To run the tests you need a valid ContactHub account and a test workspace, refer to the notes in the example to set the correct environment variables.


This library uses Immutables to generate high-quality, immutable implementations of the domain models.

This dramatically reduces the Java boilerplate code. For example, only an AbstractCustomer model is present in the src folder. When you compile it, the Customer implementation is automatically generated by Immutables and saved as target/classes/.../

Publishing to Maven Central

sbt publishSigned followed by sbt sonatypeRelease will publish a new version to Maven Central.


The version number will be generated automatically from the latest git tag by the sbt-git plugin. Before releasing, add a new git tag using the format vX.Y.Z and make sure you don't have any uncommitted changes. If there is not a tag on the latest commit or if there are uncommitted changes, a SNAPSHOT version will be created.


  • you must have the Contactlab PGP key stored in ~/.sbt/gpg/secring.asc
  • you must have the pass phrase for the Contactlab PGP key
  • you must have the password for the clab-dev Sonatype account
  • you must create the file ~/.sbt/1.0/sonatype.sbt with the following content:
credentials += Credentials("Sonatype Nexus Repository Manager",


Problem: command sbt publishSigned failed with output:

[error] secret key ring doesn't start with secret key tag: tag 0xffffffff
[error]     at org.bouncycastle.openpgp.PGPSecretKeyRing.<init>(Unknown Source)
[error]     at com.jsuereth.pgp.SecretKeyRing$.load(SecretKeyRing.scala:49)
[error]     at com.jsuereth.pgp.SecretKeyRing$.load(SecretKeyRing.scala:45)

The problem could be checking Contactlab PGP under path ~/.gnupg/secring.gpg instead of ~/.sbt/gpg/secring.asc

To fix it: Possible solutions:

  1. Preferred - store the Contactlab PGP key in ~/.gnupg/secring.gpg.
  2. rename the ~/.gnupg folder in order to force sbt to search the GPG key inside ~/.sbt/gpg/.