diff --git a/pom.xml b/pom.xml
index ef903b781f..431dc88523 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,6 +98,7 @@
     <gbif-postal-service.version>1.8.0</gbif-postal-service.version>
     <xoai.version>4.1.0-gbif-4</xoai.version>
     <gbif-occurrence.version>0.195.1</gbif-occurrence.version>
+    <checklistbank.version>2.125</checklistbank.version>
 
     <!-- Third party -->
     <commons-digester.version>3.2</commons-digester.version>
@@ -361,6 +362,11 @@
         <artifactId>occurrence-ws-client</artifactId>
         <version>${gbif-occurrence.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.gbif.checklistbank</groupId>
+        <artifactId>checklistbank-ws-client</artifactId>
+        <version>${checklistbank.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.gbif</groupId>
         <artifactId>gbif-doi</artifactId>
diff --git a/registry-cli/src/main/java/org/gbif/registry/cli/datasetindex/SpringContextBuilder.java b/registry-cli/src/main/java/org/gbif/registry/cli/datasetindex/SpringContextBuilder.java
index aee96f1719..57eff247a6 100644
--- a/registry-cli/src/main/java/org/gbif/registry/cli/datasetindex/SpringContextBuilder.java
+++ b/registry-cli/src/main/java/org/gbif/registry/cli/datasetindex/SpringContextBuilder.java
@@ -26,7 +26,7 @@
 import org.gbif.registry.search.dataset.indexing.es.EsClient;
 import org.gbif.registry.search.dataset.indexing.es.EsConfiguration;
 import org.gbif.registry.search.dataset.indexing.ws.GbifApiServiceConfig;
-import org.gbif.registry.search.dataset.indexing.ws.GbifWsRetrofitClient;
+import org.gbif.registry.search.dataset.indexing.ws.GbifWsWrapperClient;
 import org.gbif.registry.search.dataset.indexing.ws.JacksonObjectMapper;
 import org.gbif.registry.ws.client.DatasetClient;
 import org.gbif.registry.ws.client.InstallationClient;
@@ -93,7 +93,7 @@ private static AnnotationConfigApplicationContext commonContext(
         "DatasetIndexConfiguration", DatasetIndexConfiguration.class, () -> configuration);
     ctx.register(DatasetBatchIndexer.class);
     ctx.register(GbifApiServiceConfig.class);
-    ctx.register(GbifWsRetrofitClient.class);
+    ctx.register(GbifWsWrapperClient.class);
     ctx.register(JacksonObjectMapper.class);
     ctx.register(EsConfiguration.class);
     ctx.register(EsClient.class);
diff --git a/registry-integration-tests/src/test/java/org/gbif/registry/search/SearchTestConfiguration.java b/registry-integration-tests/src/test/java/org/gbif/registry/search/SearchTestConfiguration.java
index f01ecd8011..bbc200f7fc 100644
--- a/registry-integration-tests/src/test/java/org/gbif/registry/search/SearchTestConfiguration.java
+++ b/registry-integration-tests/src/test/java/org/gbif/registry/search/SearchTestConfiguration.java
@@ -13,29 +13,22 @@
  */
 package org.gbif.registry.search;
 
-import org.gbif.api.model.checklistbank.DatasetMetrics;
-import org.gbif.api.model.checklistbank.NameUsage;
-import org.gbif.api.model.checklistbank.search.NameUsageSearchParameter;
-import org.gbif.api.model.common.search.SearchResponse;
-import org.gbif.api.model.occurrence.Occurrence;
-import org.gbif.api.model.occurrence.search.OccurrenceSearchParameter;
 import org.gbif.api.service.registry.DatasetService;
 import org.gbif.api.service.registry.InstallationService;
 import org.gbif.api.service.registry.NetworkService;
 import org.gbif.api.service.registry.OrganizationService;
-import org.gbif.registry.search.dataset.indexing.ws.GbifApiService;
+import org.gbif.checklistbank.ws.client.DatasetMetricsClient;
+import org.gbif.checklistbank.ws.client.SpeciesResourceClient;
+import org.gbif.metrics.ws.client.CubeWsClient;
+import org.gbif.occurrence.ws.client.OccurrenceWsSearchClient;
 import org.gbif.registry.search.dataset.indexing.ws.GbifWsClient;
-import org.gbif.registry.search.dataset.indexing.ws.GbifWsRetrofitClient;
-
-import java.util.Map;
+import org.gbif.registry.search.dataset.indexing.ws.GbifWsWrapperClient;
 
+import org.mockito.Mockito;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
 
-import retrofit2.Call;
-import retrofit2.mock.Calls;
-
 @Configuration(proxyBeanMethods = false)
 public class SearchTestConfiguration {
 
@@ -46,38 +39,14 @@ public GbifWsClient gbifWsClient(
       OrganizationService organizationService,
       DatasetService datasetService,
       NetworkService networkService) {
-    return new GbifWsRetrofitClient(
-        gbifApiService(), installationService, organizationService, datasetService, networkService);
+      return new GbifWsWrapperClient(installationService,
+                                      organizationService,
+                                      datasetService,
+                                      networkService,
+                                      Mockito.mock(OccurrenceWsSearchClient.class),
+                                      Mockito.mock(SpeciesResourceClient.class),
+                                      Mockito.mock(CubeWsClient.class),
+                                      Mockito.mock(DatasetMetricsClient.class));
   }
 
-  public GbifApiService gbifApiService() {
-    return new GbifApiService() {
-      @Override
-      public Call<Long> getDatasetRecordCount(String datasetKey) {
-        return Calls.response(1L);
-      }
-
-      @Override
-      public Call<Long> getOccurrenceRecordCount() {
-        return Calls.response(1L);
-      }
-
-      @Override
-      public Call<DatasetMetrics> getDatasetSpeciesMetrics(String datasetKey) {
-        return Calls.response(new DatasetMetrics());
-      }
-
-      @Override
-      public Call<SearchResponse<NameUsage, NameUsageSearchParameter>> speciesSearch(
-          Map<String, Object> options) {
-        return Calls.response(new SearchResponse<>());
-      }
-
-      @Override
-      public Call<SearchResponse<Occurrence, OccurrenceSearchParameter>> occurrenceSearch(
-          Map<String, Object> options) {
-        return Calls.response(new SearchResponse<>());
-      }
-    };
-  }
 }
diff --git a/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/OccurrenceDownloadIT.java b/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/OccurrenceDownloadIT.java
index 2d367e88a9..80081947e9 100644
--- a/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/OccurrenceDownloadIT.java
+++ b/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/OccurrenceDownloadIT.java
@@ -20,8 +20,8 @@
 import org.gbif.api.model.occurrence.DownloadFormat;
 import org.gbif.api.model.occurrence.DownloadType;
 import org.gbif.api.model.occurrence.PredicateDownloadRequest;
-import org.gbif.api.model.predicate.EqualsPredicate;
 import org.gbif.api.model.occurrence.search.OccurrenceSearchParameter;
+import org.gbif.api.model.predicate.EqualsPredicate;
 import org.gbif.api.model.registry.CountryOccurrenceDownloadUsage;
 import org.gbif.api.model.registry.Dataset;
 import org.gbif.api.model.registry.DatasetOccurrenceDownloadUsage;
diff --git a/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/collections/service/LookupServiceIT.java b/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/collections/service/LookupServiceIT.java
index b09053a012..5214ec9169 100644
--- a/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/collections/service/LookupServiceIT.java
+++ b/registry-integration-tests/src/test/java/org/gbif/registry/ws/it/collections/service/LookupServiceIT.java
@@ -13,8 +13,8 @@
  */
 package org.gbif.registry.ws.it.collections.service;
 
-import org.gbif.api.model.collections.Address;
 import org.gbif.api.model.collections.*;
+import org.gbif.api.model.collections.Address;
 import org.gbif.api.model.collections.lookup.*;
 import org.gbif.api.model.registry.*;
 import org.gbif.api.service.collections.CollectionService;
@@ -27,15 +27,16 @@
 import org.gbif.registry.database.TestCaseDatabaseInitializer;
 import org.gbif.registry.service.collections.lookup.LookupService;
 import org.gbif.ws.client.filter.SimplePrincipalProvider;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.springframework.beans.factory.annotation.Autowired;
 
 import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+
 import static org.junit.Assert.assertNull;
 import static org.junit.jupiter.api.Assertions.*;
 
diff --git a/registry-oaipmh/src/main/java/org/gbif/registry/oaipmh/OaipmhItemRepository.java b/registry-oaipmh/src/main/java/org/gbif/registry/oaipmh/OaipmhItemRepository.java
index fa0bb5e1b7..3ad98cc2cc 100644
--- a/registry-oaipmh/src/main/java/org/gbif/registry/oaipmh/OaipmhItemRepository.java
+++ b/registry-oaipmh/src/main/java/org/gbif/registry/oaipmh/OaipmhItemRepository.java
@@ -56,11 +56,11 @@
 import org.dspace.xoai.dataprovider.repository.ItemRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.util.LinkedMultiValueMap;
 
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
 
 import static org.gbif.registry.oaipmh.OaipmhSetRepository.SetType.COUNTRY;
 import static org.gbif.registry.oaipmh.OaipmhSetRepository.SetType.DATASET_TYPE;
@@ -297,8 +297,9 @@ private OaipmhItem toOaipmhItem(Dataset dataset) throws IOException {
     ReadBuilder readBuilder = new ReadBuilder();
     readBuilder.at(OccurrenceCube.DATASET_KEY, dataset.getKey());
     try {
-      Long occurrenceCount =
-          metricsClient.count(ImmutableMap.of("datasetKey", dataset.getKey().toString()));
+      LinkedMultiValueMap<String,String> params = new LinkedMultiValueMap<>();
+      params.add("datasetKey", dataset.getKey().toString());
+      long occurrenceCount = metricsClient.get(params);
       if (occurrenceCount > 0) {
         additionalProperties.put(DublinCoreWriter.ADDITIONAL_PROPERTY_OCC_COUNT, occurrenceCount);
       }
diff --git a/registry-persistence/src/main/java/org/gbif/registry/persistence/config/MyBatisConfiguration.java b/registry-persistence/src/main/java/org/gbif/registry/persistence/config/MyBatisConfiguration.java
index 11c78229c5..4a3be713fd 100644
--- a/registry-persistence/src/main/java/org/gbif/registry/persistence/config/MyBatisConfiguration.java
+++ b/registry-persistence/src/main/java/org/gbif/registry/persistence/config/MyBatisConfiguration.java
@@ -26,10 +26,10 @@
 import org.gbif.api.model.occurrence.DownloadRequest;
 import org.gbif.api.model.occurrence.PredicateDownloadRequest;
 import org.gbif.api.model.occurrence.SqlDownloadRequest;
-import org.gbif.api.model.predicate.Predicate;
 import org.gbif.api.model.pipelines.PipelineExecution;
 import org.gbif.api.model.pipelines.PipelineProcess;
 import org.gbif.api.model.pipelines.PipelineStep;
+import org.gbif.api.model.predicate.Predicate;
 import org.gbif.api.model.registry.Citation;
 import org.gbif.api.model.registry.Comment;
 import org.gbif.api.model.registry.Contact;
diff --git a/registry-persistence/src/main/java/org/gbif/registry/persistence/mapper/DatasetProcessStatusMapper.java b/registry-persistence/src/main/java/org/gbif/registry/persistence/mapper/DatasetProcessStatusMapper.java
index 067deecfb8..e1a08bf4f2 100644
--- a/registry-persistence/src/main/java/org/gbif/registry/persistence/mapper/DatasetProcessStatusMapper.java
+++ b/registry-persistence/src/main/java/org/gbif/registry/persistence/mapper/DatasetProcessStatusMapper.java
@@ -13,16 +13,18 @@
  */
 package org.gbif.registry.persistence.mapper;
 
-import org.apache.ibatis.annotations.Param;
 import org.gbif.api.model.common.paging.Pageable;
 import org.gbif.api.model.crawler.DatasetProcessStatus;
 import org.gbif.api.model.crawler.FinishReason;
-import org.springframework.stereotype.Repository;
 
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
 /** Mapper that perform operations on {@link DatasetProcessStatus} instances. */
 @Repository
 public interface DatasetProcessStatusMapper {
diff --git a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/DefaultRegistryIngestionHistoryService.java b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/DefaultRegistryIngestionHistoryService.java
index e3a2c07d62..10b7b5c924 100644
--- a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/DefaultRegistryIngestionHistoryService.java
+++ b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/DefaultRegistryIngestionHistoryService.java
@@ -23,15 +23,17 @@
 import org.gbif.registry.persistence.mapper.DatasetMapper;
 import org.gbif.registry.persistence.mapper.DatasetProcessStatusMapper;
 import org.gbif.registry.persistence.mapper.pipelines.PipelineProcessMapper;
-import org.springframework.stereotype.Service;
 
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
+import javax.annotation.Nullable;
+
+import org.springframework.stereotype.Service;
+
 @Service
 public class DefaultRegistryIngestionHistoryService implements RegistryIngestionHistoryService {
 
diff --git a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/RegistryIngestionHistoryService.java b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/RegistryIngestionHistoryService.java
index 2f52adb30e..633b4efaab 100644
--- a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/RegistryIngestionHistoryService.java
+++ b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/RegistryIngestionHistoryService.java
@@ -18,10 +18,11 @@
 import org.gbif.api.model.crawler.FinishReason;
 import org.gbif.api.model.pipelines.IngestionProcess;
 
-import javax.annotation.Nullable;
 import java.util.List;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+
 public interface RegistryIngestionHistoryService {
 
   PagingResponse<IngestionProcess> ingestionHistory(
diff --git a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/GithubClientConfig.java b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/GithubClientConfig.java
index ebcc651acb..4f71b7cc95 100644
--- a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/GithubClientConfig.java
+++ b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/GithubClientConfig.java
@@ -13,11 +13,13 @@
  */
 package org.gbif.registry.pipelines.issues;
 
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+
 import okhttp3.OkHttpClient;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
 import retrofit2.Retrofit;
 import retrofit2.converter.jackson.JacksonConverterFactory;
 
diff --git a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssueCreator.java b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssueCreator.java
index 9016790ac0..54dd29a49c 100644
--- a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssueCreator.java
+++ b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssueCreator.java
@@ -13,21 +13,6 @@
  */
 package org.gbif.registry.pipelines.issues;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.avro.file.DataFileReader;
-import org.apache.avro.generic.GenericDatumReader;
-import org.apache.avro.generic.GenericRecord;
-import org.apache.avro.io.DatumReader;
-import org.apache.commons.io.IOUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.AvroFSInput;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.LocatedFileStatus;
-import org.apache.hadoop.fs.RemoteIterator;
 import org.gbif.api.model.common.search.SearchResponse;
 import org.gbif.api.model.occurrence.Occurrence;
 import org.gbif.api.model.occurrence.search.OccurrenceSearchParameter;
@@ -44,11 +29,6 @@
 import org.gbif.registry.persistence.mapper.pipelines.PipelineProcessMapper;
 import org.gbif.ws.client.ClientBuilder;
 import org.gbif.ws.json.JacksonJsonObjectMapperProvider;
-import org.jetbrains.annotations.NotNull;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.stereotype.Component;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -60,6 +40,29 @@
 import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
 
+import org.apache.avro.file.DataFileReader;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.avro.io.DatumReader;
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.AvroFSInput;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.LocatedFileStatus;
+import org.apache.hadoop.fs.RemoteIterator;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+
 import static org.gbif.registry.pipelines.issues.GithubApiService.Issue;
 
 @Component
diff --git a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssuesConfig.java b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssuesConfig.java
index 25a881da36..e92bb98775 100644
--- a/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssuesConfig.java
+++ b/registry-pipelines/src/main/java/org/gbif/registry/pipelines/issues/IssuesConfig.java
@@ -13,12 +13,13 @@
  */
 package org.gbif.registry.pipelines.issues;
 
-import lombok.Getter;
-import lombok.Setter;
+import javax.validation.constraints.NotEmpty;
+
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
-import javax.validation.constraints.NotEmpty;
+import lombok.Getter;
+import lombok.Setter;
 
 @Component
 @Getter
diff --git a/registry-search/pom.xml b/registry-search/pom.xml
index 62f4ee2bc1..5798c89387 100644
--- a/registry-search/pom.xml
+++ b/registry-search/pom.xml
@@ -59,35 +59,6 @@
       <groupId>org.postgresql</groupId>
       <artifactId>postgresql</artifactId>
     </dependency>
-    <dependency>
-      <groupId>com.squareup.retrofit2</groupId>
-      <artifactId>retrofit</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.squareup.retrofit2</groupId>
-      <artifactId>converter-jackson</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.squareup.retrofit2</groupId>
-      <artifactId>converter-simplexml</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.squareup.retrofit2</groupId>
-      <artifactId>converter-scalars</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.squareup.okhttp3</groupId>
-      <artifactId>okhttp</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.squareup.okhttp3</groupId>
-      <artifactId>logging-interceptor</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.squareup.okio</groupId>
-      <artifactId>okio</artifactId>
-      <scope>runtime</scope>
-    </dependency>
 
     <!-- ES -->
     <dependency>
@@ -127,6 +98,14 @@
       <groupId>org.gbif.registry</groupId>
       <artifactId>registry-ws-client</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.gbif.checklistbank</groupId>
+      <artifactId>checklistbank-ws-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.gbif.occurrence</groupId>
+      <artifactId>occurrence-ws-client</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.testcontainers</groupId>
diff --git a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifApiServiceConfig.java b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifApiServiceConfig.java
index fdd0d08567..32566db492 100644
--- a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifApiServiceConfig.java
+++ b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifApiServiceConfig.java
@@ -13,7 +13,12 @@
  */
 package org.gbif.registry.search.dataset.indexing.ws;
 
-import java.util.concurrent.TimeUnit;
+
+import org.gbif.checklistbank.ws.client.DatasetMetricsClient;
+import org.gbif.checklistbank.ws.client.SpeciesResourceClient;
+import org.gbif.metrics.ws.client.CubeWsClient;
+import org.gbif.occurrence.ws.client.OccurrenceWsSearchClient;
+import org.gbif.ws.client.ClientBuilder;
 
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
@@ -22,31 +27,47 @@
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import okhttp3.OkHttpClient;
-import retrofit2.Retrofit;
-import retrofit2.converter.jackson.JacksonConverterFactory;
 
 @Configuration
 public class GbifApiServiceConfig {
 
   @Bean
-  public GbifApiService gbifApiService(
+  public OccurrenceWsSearchClient occurrenceWsSearchClient(
       @Value("${api.root.url}") String apiBaseUrl,
       @Qualifier("apiMapper") ObjectMapper objectMapper) {
+    return new ClientBuilder()
+            .withObjectMapper(objectMapper)
+            .withUrl(apiBaseUrl)
+            .build(OccurrenceWsSearchClient.class);
+  }
+
+  @Bean
+  public CubeWsClient cubeWsClient(
+    @Value("${api.root.url}") String apiBaseUrl,
+    @Qualifier("apiMapper") ObjectMapper objectMapper) {
+    return new ClientBuilder()
+      .withObjectMapper(objectMapper)
+      .withUrl(apiBaseUrl)
+      .build(CubeWsClient.class);
+  }
 
-    OkHttpClient okHttpClient =
-        new OkHttpClient()
-            .newBuilder()
-            .connectTimeout(2, TimeUnit.MINUTES)
-            .readTimeout(5, TimeUnit.MINUTES)
-            .writeTimeout(1, TimeUnit.MINUTES)
-            .build();
-    Retrofit retrofit =
-        new Retrofit.Builder()
-            .baseUrl(apiBaseUrl)
-            .addConverterFactory(JacksonConverterFactory.create(objectMapper))
-            .client(okHttpClient)
-            .build();
-    return retrofit.create(GbifApiService.class);
+  @Bean
+  public DatasetMetricsClient datasetMetricsClient(
+    @Value("${api.root.url}") String apiBaseUrl,
+    @Qualifier("apiMapper") ObjectMapper objectMapper) {
+    return new ClientBuilder()
+      .withObjectMapper(objectMapper)
+      .withUrl(apiBaseUrl)
+      .build(DatasetMetricsClient.class);
+  }
+
+  @Bean
+  public SpeciesResourceClient speciesResourceClient(
+    @Value("${api.root.url}") String apiBaseUrl,
+    @Qualifier("apiMapper") ObjectMapper objectMapper) {
+    return new ClientBuilder()
+      .withObjectMapper(objectMapper)
+      .withUrl(apiBaseUrl)
+      .build(SpeciesResourceClient.class);
   }
 }
diff --git a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsClient.java b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsClient.java
index dee8300e41..d1e1d00ccb 100644
--- a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsClient.java
+++ b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsClient.java
@@ -14,9 +14,9 @@
 package org.gbif.registry.search.dataset.indexing.ws;
 
 import org.gbif.api.model.checklistbank.DatasetMetrics;
-import org.gbif.api.model.checklistbank.NameUsage;
 import org.gbif.api.model.checklistbank.search.NameUsageSearchParameter;
 import org.gbif.api.model.checklistbank.search.NameUsageSearchRequest;
+import org.gbif.api.model.checklistbank.search.NameUsageSearchResult;
 import org.gbif.api.model.common.paging.PagingRequest;
 import org.gbif.api.model.common.paging.PagingResponse;
 import org.gbif.api.model.common.search.SearchResponse;
@@ -63,7 +63,7 @@ PagingResponse<Dataset> getOrganizationPublishedDataset(
 
   DatasetMetrics getDatasetSpeciesMetrics(String datasetKey);
 
-  SearchResponse<NameUsage, NameUsageSearchParameter> speciesSearch(
+  SearchResponse<NameUsageSearchResult, NameUsageSearchParameter> speciesSearch(
       NameUsageSearchRequest searchRequest);
 
   SearchResponse<Occurrence, OccurrenceSearchParameter> occurrenceSearch(
diff --git a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsRetrofitClient.java b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsWrapperClient.java
similarity index 76%
rename from registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsRetrofitClient.java
rename to registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsWrapperClient.java
index a6bc5eabf4..f53631e98b 100644
--- a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsRetrofitClient.java
+++ b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/GbifWsWrapperClient.java
@@ -14,12 +14,11 @@
 package org.gbif.registry.search.dataset.indexing.ws;
 
 import org.gbif.api.model.checklistbank.DatasetMetrics;
-import org.gbif.api.model.checklistbank.NameUsage;
 import org.gbif.api.model.checklistbank.search.NameUsageSearchParameter;
 import org.gbif.api.model.checklistbank.search.NameUsageSearchRequest;
+import org.gbif.api.model.checklistbank.search.NameUsageSearchResult;
 import org.gbif.api.model.common.paging.PagingRequest;
 import org.gbif.api.model.common.paging.PagingResponse;
-import org.gbif.api.model.common.search.SearchParameter;
 import org.gbif.api.model.common.search.SearchResponse;
 import org.gbif.api.model.occurrence.Occurrence;
 import org.gbif.api.model.occurrence.search.OccurrenceSearchParameter;
@@ -32,11 +31,13 @@
 import org.gbif.api.service.registry.InstallationService;
 import org.gbif.api.service.registry.NetworkService;
 import org.gbif.api.service.registry.OrganizationService;
+import org.gbif.checklistbank.ws.client.DatasetMetricsClient;
+import org.gbif.checklistbank.ws.client.SpeciesResourceClient;
+import org.gbif.metrics.ws.client.CubeWsClient;
+import org.gbif.occurrence.ws.client.OccurrenceWsSearchClient;
 
 import java.io.InputStream;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
 import org.cache2k.Cache;
@@ -44,15 +45,12 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
-
-import lombok.SneakyThrows;
-import retrofit2.Call;
-import retrofit2.Response;
+import org.springframework.util.LinkedMultiValueMap;
 
 /** Retrofit {@link GbifApiService} client. */
 @Component
 @Lazy
-public class GbifWsRetrofitClient implements GbifWsClient {
+public class GbifWsWrapperClient implements GbifWsClient {
 
   // Uses a cache for installations to avoid too many external calls
   Cache<String, Installation> installationCache =
@@ -72,12 +70,15 @@ public class GbifWsRetrofitClient implements GbifWsClient {
           .loader(this::loadOrganization)
           .build();
 
-  private final GbifApiService gbifApiService;
-
   private final InstallationService installationService;
   private final OrganizationService organizationService;
   private final DatasetService datasetService;
   private final NetworkService networkService;
+  private final OccurrenceWsSearchClient occurrenceWsSearchClient;
+  private final SpeciesResourceClient speciesResourceClient;
+  private final CubeWsClient cubeWsClient;
+
+  private final DatasetMetricsClient datasetMetricsClient;
 
   /**
    * Factory method, only need the api base url.
@@ -85,24 +86,23 @@ public class GbifWsRetrofitClient implements GbifWsClient {
    * @param apiBaseUrl GBIF Api base url, for example: https://api.gbif-dev.orf/v1/ .
    */
   @Autowired
-  public GbifWsRetrofitClient(
-      GbifApiService gbifApiService,
+  public GbifWsWrapperClient(
       InstallationService installationService,
       OrganizationService organizationService,
       DatasetService datasetService,
-      NetworkService networkService) {
-    this.gbifApiService = gbifApiService;
+      NetworkService networkService,
+      OccurrenceWsSearchClient occurrenceWsSearchClient,
+      SpeciesResourceClient speciesResourceClient,
+      CubeWsClient cubeWsClient,
+      DatasetMetricsClient datasetMetricsClient) {
     this.installationService = installationService;
     this.organizationService = organizationService;
     this.datasetService = datasetService;
     this.networkService = networkService;
-  }
-
-  private Map<String, String> toQueryMap(PagingRequest pagingRequest) {
-    Map<String, String> params = new HashMap<>();
-    params.put("offset", Long.toString(pagingRequest.getOffset()));
-    params.put("limit", Long.toString(pagingRequest.getLimit()));
-    return params;
+    this.occurrenceWsSearchClient = occurrenceWsSearchClient;
+    this.speciesResourceClient = speciesResourceClient;
+    this.cubeWsClient = cubeWsClient;
+    this.datasetMetricsClient = datasetMetricsClient;
   }
 
   @Override
@@ -169,50 +169,35 @@ public InputStream getMetadataDocument(UUID datasetKey) {
 
   @Override
   public Long getDatasetRecordCount(String datasetKey) {
-    return syncCallWithResponse(gbifApiService.getDatasetRecordCount(datasetKey)).body();
+    LinkedMultiValueMap<String,String> params = new LinkedMultiValueMap<>();
+    params.add("datasetKey", datasetKey);
+    return cubeWsClient.get(params);
   }
 
   @Override
   public Long getOccurrenceRecordCount() {
-    return syncCallWithResponse(gbifApiService.getOccurrenceRecordCount()).body();
+    return cubeWsClient.get(new LinkedMultiValueMap<>());
   }
 
   @Override
   public DatasetMetrics getDatasetSpeciesMetrics(String datasetKey) {
-    return syncCallWithResponse(gbifApiService.getDatasetSpeciesMetrics(datasetKey)).body();
+    return datasetMetricsClient.get(UUID.fromString(datasetKey));
   }
 
   @Override
-  public SearchResponse<NameUsage, NameUsageSearchParameter> speciesSearch(
+  public SearchResponse<NameUsageSearchResult, NameUsageSearchParameter> speciesSearch(
       NameUsageSearchRequest searchRequest) {
-    return syncCallWithResponse(
-            gbifApiService.speciesSearch(SearchParameterProvider.getParameterFromFacetedRequest(searchRequest)))
-        .body();
+    return speciesResourceClient.search(searchRequest);
   }
 
   @Override
   public SearchResponse<Occurrence, OccurrenceSearchParameter> occurrenceSearch(
       OccurrenceSearchRequest searchRequest) {
-    return syncCallWithResponse(
-            gbifApiService.occurrenceSearch(SearchParameterProvider.getParameterFromFacetedRequest(searchRequest)))
-        .body();
+    return occurrenceWsSearchClient.search(searchRequest);
   }
 
   @Override
   public List<Network> getNetworks(UUID datasetKey) {
     return datasetService.listNetworks(datasetKey);
   }
-
-  /**
-   * Performs a synchronous call to {@link Call} instance.
-   *
-   * @param call to be executed
-   * @param <T> content of the response object
-   * @return {@link Response} with content, throws a {@link RuntimeException} when IOException was
-   *     thrown from execute method
-   */
-  @SneakyThrows
-  private static <T> Response<T> syncCallWithResponse(Call<T> call) {
-    return call.execute();
-  }
 }
diff --git a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/SearchParameterProvider.java b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/SearchParameterProvider.java
index 8df3310b05..a99317cee7 100644
--- a/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/SearchParameterProvider.java
+++ b/registry-search/src/main/java/org/gbif/registry/search/dataset/indexing/ws/SearchParameterProvider.java
@@ -18,6 +18,7 @@
 import org.gbif.api.model.common.search.FacetedSearchRequest;
 import org.gbif.api.model.common.search.SearchParameter;
 import org.gbif.api.model.common.search.SearchRequest;
+import org.gbif.api.model.occurrence.search.OccurrenceSearchRequest;
 
 import java.util.AbstractMap;
 import java.util.HashMap;
@@ -34,8 +35,6 @@
 
 import lombok.experimental.UtilityClass;
 
-import org.gbif.api.model.occurrence.search.OccurrenceSearchRequest;
-
 import static org.gbif.registry.search.dataset.indexing.ws.WebserviceParameter.DEFAULT_SEARCH_PARAM_VALUE;
 import static org.gbif.registry.search.dataset.indexing.ws.WebserviceParameter.PARAM_FACET;
 import static org.gbif.registry.search.dataset.indexing.ws.WebserviceParameter.PARAM_FACET_LIMIT;
diff --git a/registry-service/src/main/java/org/gbif/registry/service/collections/lookup/matchers/CollectionMatcher.java b/registry-service/src/main/java/org/gbif/registry/service/collections/lookup/matchers/CollectionMatcher.java
index 168dcd76b8..3bd932dad4 100644
--- a/registry-service/src/main/java/org/gbif/registry/service/collections/lookup/matchers/CollectionMatcher.java
+++ b/registry-service/src/main/java/org/gbif/registry/service/collections/lookup/matchers/CollectionMatcher.java
@@ -21,13 +21,14 @@
 import org.gbif.registry.persistence.mapper.collections.LookupMapper;
 import org.gbif.registry.persistence.mapper.collections.dto.CollectionMatchedDto;
 import org.gbif.registry.service.collections.lookup.Matches;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
 
 import java.net.URI;
 import java.util.*;
 
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
 import static org.gbif.api.model.collections.lookup.Match.Reason.INST_COLL_MISMATCH;
 
 @Component
diff --git a/registry-service/src/test/java/org/gbif/registry/service/collections/lookup/matchers/MatchersTest.java b/registry-service/src/test/java/org/gbif/registry/service/collections/lookup/matchers/MatchersTest.java
index ed0ef317ca..309b1a2be7 100644
--- a/registry-service/src/test/java/org/gbif/registry/service/collections/lookup/matchers/MatchersTest.java
+++ b/registry-service/src/test/java/org/gbif/registry/service/collections/lookup/matchers/MatchersTest.java
@@ -13,10 +13,10 @@
  */
 package org.gbif.registry.service.collections.lookup.matchers;
 
-import org.junit.jupiter.api.Test;
-
 import java.util.UUID;
 
+import org.junit.jupiter.api.Test;
+
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
diff --git a/registry-ws/src/main/java/org/gbif/registry/ws/resources/collections/BaseCollectionEntityResource.java b/registry-ws/src/main/java/org/gbif/registry/ws/resources/collections/BaseCollectionEntityResource.java
index 06ee78cd81..d751f7cab4 100644
--- a/registry-ws/src/main/java/org/gbif/registry/ws/resources/collections/BaseCollectionEntityResource.java
+++ b/registry-ws/src/main/java/org/gbif/registry/ws/resources/collections/BaseCollectionEntityResource.java
@@ -13,24 +13,12 @@
  */
 package org.gbif.registry.ws.resources.collections;
 
-import com.google.common.base.Preconditions;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.enums.Explode;
-import io.swagger.v3.oas.annotations.enums.ParameterIn;
-import io.swagger.v3.oas.annotations.extensions.Extension;
-import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import lombok.SneakyThrows;
 import org.gbif.api.annotation.EmptyToNull;
 import org.gbif.api.annotation.NullToNotFound;
 import org.gbif.api.annotation.Trim;
 import org.gbif.api.documentation.CommonParameters;
-import org.gbif.api.model.collections.Contact;
 import org.gbif.api.model.collections.*;
+import org.gbif.api.model.collections.Contact;
 import org.gbif.api.model.collections.duplicates.DuplicatesRequest;
 import org.gbif.api.model.collections.duplicates.DuplicatesResult;
 import org.gbif.api.model.collections.merge.MergeParams;
@@ -52,20 +40,7 @@
 import org.gbif.registry.service.collections.duplicates.DuplicatesService;
 import org.gbif.registry.service.collections.merge.MergeService;
 import org.gbif.registry.ws.resources.Docs;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.core.io.ByteArrayResource;
-import org.springframework.core.io.Resource;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.StreamUtils;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
 
-import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -78,6 +53,35 @@
 import java.util.List;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StreamUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.common.base.Preconditions;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.Explode;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.extensions.Extension;
+import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import lombok.SneakyThrows;
+
 import static com.google.common.base.Preconditions.checkArgument;
 
 /** Base class to implement the CRUD methods of a {@link CollectionEntity}. */
diff --git a/registry-ws/src/main/java/org/gbif/registry/ws/resources/pipelines/IngestionHistoryResource.java b/registry-ws/src/main/java/org/gbif/registry/ws/resources/pipelines/IngestionHistoryResource.java
index 54df55f755..e06892362b 100644
--- a/registry-ws/src/main/java/org/gbif/registry/ws/resources/pipelines/IngestionHistoryResource.java
+++ b/registry-ws/src/main/java/org/gbif/registry/ws/resources/pipelines/IngestionHistoryResource.java
@@ -13,20 +13,23 @@
  */
 package org.gbif.registry.ws.resources.pipelines;
 
-import io.swagger.v3.oas.annotations.Hidden;
 import org.gbif.api.model.common.paging.Pageable;
 import org.gbif.api.model.common.paging.PagingResponse;
 import org.gbif.api.model.crawler.FinishReason;
 import org.gbif.api.model.pipelines.IngestionProcess;
 import org.gbif.api.service.pipelines.IngestionHistoryService;
 import org.gbif.registry.pipelines.RegistryIngestionHistoryService;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
 import org.springframework.http.MediaType;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Nullable;
-import java.util.List;
-import java.util.UUID;
+import io.swagger.v3.oas.annotations.Hidden;
 
 @Hidden // TODO: Document?
 @RestController