diff --git a/composer.json b/composer.json
index 037e9199eee7c270db13878f0376abd131b2df91..b96738b491dd41139c6f6100c4fc4e822657f02c 100644
--- a/composer.json
+++ b/composer.json
@@ -32,6 +32,7 @@
     "drupal/encrypt": "^3.0@rc",
     "drupal/key": "^1.7",
     "lusitanian/oauth": "^0.8.11",
-    "firebase/php-jwt": "^5.0"
+    "firebase/php-jwt": "^5.0",
+    "messageagency/force.com-toolkit-for-php": "^1.0.0"
   }
 }
diff --git a/modules/salesforce_mapping/src/Commands/SalesforceMappingCommands.php b/modules/salesforce_mapping/src/Commands/SalesforceMappingCommands.php
index 288af9a0c96c9eb5a791100c3b1edf5276e29266..7be495ee95b67c03dbac46e9a89d5e8dc880fbab 100644
--- a/modules/salesforce_mapping/src/Commands/SalesforceMappingCommands.php
+++ b/modules/salesforce_mapping/src/Commands/SalesforceMappingCommands.php
@@ -5,7 +5,6 @@ namespace Drupal\salesforce_mapping\Commands;
 use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\salesforce\Commands\SalesforceCommandsBase;
 use Drupal\salesforce\Rest\RestClient;
 use Drupal\salesforce\SelectQuery;
 use Drush\Exceptions\UserAbortException;
@@ -23,7 +22,7 @@ use Symfony\Component\Console\Output\Output;
  *   - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
  *   - http://cgit.drupalcode.org/devel/tree/drush.services.yml
  */
-class SalesforceMappingCommands extends SalesforceCommandsBase {
+class SalesforceMappingCommands extends SalesforceMappingCommandsBase {
 
   protected $salesforceConfig;
   protected $database;
diff --git a/modules/salesforce_mapping/src/Commands/SalesforceMappingCommandsBase.php b/modules/salesforce_mapping/src/Commands/SalesforceMappingCommandsBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..f544e070055c1b3e6ec3408ab9684fc97bd6ef1d
--- /dev/null
+++ b/modules/salesforce_mapping/src/Commands/SalesforceMappingCommandsBase.php
@@ -0,0 +1,209 @@
+<?php
+
+namespace Drupal\salesforce_mapping\Commands;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\salesforce\Rest\RestClient;
+use Drush\Drush;
+use Drush\Exceptions\UserAbortException;
+use Symfony\Component\Console\Input\Input;
+use Symfony\Component\Console\Output\Output;
+use Drupal\salesforce\Commands\SalesforceCommandsBase;
+use Drupal\salesforce\Commands\QueryResult;
+use Drupal\salesforce\Commands\QueryResultTableFormatter;
+
+/**
+ * Shared command base for Salesforce Drush commands.
+ */
+abstract class SalesforceMappingCommandsBase extends SalesforceCommandsBase {
+
+  /**
+   * Salesforce Mapping storage handler.
+   *
+   * @var \Drupal\salesforce_mapping\SalesforceMappingStorage
+   */
+  protected $mappingStorage;
+
+  /**
+   * Mapped Object storage handler.
+   *
+   * @var \Drupal\salesforce_mapping\MappedObjectStorage
+   */
+  protected $mappedObjectStorage;
+
+  /**
+   * SalesforceMappingCommandsBase constructor.
+   *
+   * @param \Drupal\salesforce\Rest\RestClient $client
+   *   SF client.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $etm
+   *   Entity type manager.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+   */
+  public function __construct(RestClient $client, EntityTypeManagerInterface $etm) {
+    parent::__construct($client, $etm);
+
+    $this->mappingStorage = $etm->getStorage('salesforce_mapping');
+    $this->mappedObjectStorage = $etm->getStorage('salesforce_mapped_object');
+  }
+
+  /**
+   * Collect a salesforce mapping interactively.
+   */
+  protected function interactMapping(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE, $dir = NULL) {
+    if ($name = $input->getArgument('name')) {
+      if (strtoupper($name) == 'ALL') {
+        $input->setArgument('name', 'ALL');
+        return;
+      }
+      /** @var \Drupal\salesforce_mapping\Entity\SalesforceMapping $mapping */
+      $mapping = $this->mappingStorage->load($name);
+      if (!$mapping) {
+        $this->logger()->error(dt('Mapping %name does not exist.', ['%name' => $name]));
+      }
+      elseif ($dir == 'push' && !$mapping->doesPush()) {
+        $this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
+      }
+      elseif ($dir == 'pull' && !$mapping->doesPull()) {
+        $this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
+      }
+      else {
+        return;
+      }
+    }
+    if ($dir == 'pull') {
+      $options = $this->mappingStorage->loadPullMappings();
+    }
+    elseif ($dir == 'push') {
+      $options = $this->mappingStorage->loadPushMappings();
+    }
+    else {
+      $options = $this->mappingStorage->loadMultiple();
+    }
+    $this->doMappingNameOptions($input, array_keys($options), $message, $allOption);
+
+  }
+
+  /**
+   * Collect a salesforce mapping name, and set it to a "name" argument.
+   */
+  protected function interactPushMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
+    return $this->interactMapping($input, $output, $message, $allOption, 'push');
+  }
+
+  /**
+   * Collect a salesforce mapping name, and set it to a "name" argument.
+   */
+  protected function interactPullMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
+    return $this->interactMapping($input, $output, $message, $allOption, 'pull');
+  }
+
+  /**
+   * Helper method to collect the choice from user, given a set of options.
+   */
+  protected function doMappingNameOptions(Input $input, array $options, $message, $allOption = FALSE) {
+    $options = array_combine($options, $options);
+    if ($allOption) {
+      $options['ALL'] = $allOption;
+    }
+    if (!$answer = $this->io()->choice($message, $options)) {
+      throw new UserAbortException();
+    }
+    $input->setArgument('name', $answer);
+  }
+
+  /**
+   * Given a mapping name (and optional direction), get an array of mappings.
+   *
+   * @param string $name
+   *   'ALL' to load all mappings, or a mapping id.
+   * @param string $dir
+   *   'push'|'pull'|NULL to load limit mappings by push or pull types.
+   *
+   * @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
+   *   The mappings.
+   */
+  protected function getMappingsFromName($name, $dir = NULL) {
+    $mappings = [];
+    if ($name == 'ALL') {
+      if ($dir == 'pull') {
+        $mappings = $this->mappingStorage->loadPullMappings();
+      }
+      elseif ($dir == 'push') {
+        $mappings = $this->mappingStorage->loadPushMappings();
+      }
+      else {
+        $mappings = $this->mappingStorage->loadMultiple();
+      }
+    }
+    else {
+      $mapping = $this->mappingStorage->load($name);
+      if ($dir == 'push' && !$mapping->doesPush()) {
+        throw new \Exception(dt("Mapping !name does not push.", ['!name' => $name]));
+      }
+      elseif ($dir == 'pull' && !$mapping->doesPull()) {
+        throw new \Exception(dt("Mapping !name does not pull.", ['!name' => $name]));
+      }
+      $mappings = [$mapping];
+    }
+    $mappings = array_filter($mappings);
+    if (empty($mappings)) {
+      if ($dir == 'push') {
+        throw new \Exception(dt('No push mappings loaded'));
+      }
+      if ($dir == 'pull') {
+        throw new \Exception(dt('No pull mappings loaded'));
+      }
+    }
+    return $mappings;
+  }
+
+  /**
+   * Given a mapping name, get an array of matching push mappings.
+   *
+   * @param string $name
+   *   The mapping name.
+   *
+   * @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
+   *   The matching mappings.
+   *
+   * @throws \Exception
+   */
+  protected function getPushMappingsFromName($name) {
+    return $this->getMappingsFromName($name, 'push');
+  }
+
+  /**
+   * Given a mappin gname, get an array of matching pull mappings.
+   *
+   * @param string $name
+   *   The mapping name.
+   *
+   * @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
+   *   The pull mappings.
+   *
+   * @throws \Exception
+   */
+  protected function getPullMappingsFromName($name) {
+    return $this->getMappingsFromName($name, 'pull');
+  }
+
+  /**
+   * Pass-through helper to add appropriate formatters for a query result.
+   *
+   * @param \Drupal\salesforce\Commands\QueryResult $query
+   *   The query result.
+   *
+   * @return \Drupal\salesforce\Commands\QueryResult
+   *   The same, unchanged query result.
+   */
+  protected function returnQueryResult(QueryResult $query) {
+    $formatter = new QueryResultTableFormatter();
+    $formatterManager = Drush::getContainer()->get('formatterManager');
+    $formatterManager->addFormatter('table', $formatter);
+    return $query;
+  }
+
+}
diff --git a/modules/salesforce_pull/src/Commands/SalesforcePullCommands.php b/modules/salesforce_pull/src/Commands/SalesforcePullCommands.php
index 2b180bbbbbd4f422d5eee8d0c78a5615405a8113..1c21518cbe7001b4cfeaffc215abf27529664af7 100644
--- a/modules/salesforce_pull/src/Commands/SalesforcePullCommands.php
+++ b/modules/salesforce_pull/src/Commands/SalesforcePullCommands.php
@@ -4,7 +4,7 @@ namespace Drupal\salesforce_pull\Commands;
 
 use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\salesforce\Commands\SalesforceCommandsBase;
+use Drupal\salesforce_mapping\Commands\SalesforceMappingCommandsBase;
 use Drupal\salesforce\Event\SalesforceEvents;
 use Drupal\salesforce\Rest\RestClient;
 use Drupal\salesforce\SFID;
@@ -24,7 +24,7 @@ use Symfony\Component\Console\Output\Output;
  *   - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
  *   - http://cgit.drupalcode.org/devel/tree/drush.services.yml
  */
-class SalesforcePullCommands extends SalesforceCommandsBase {
+class SalesforcePullCommands extends SalesforceMappingCommandsBase {
 
   /**
    * Pull queue handler service.
diff --git a/modules/salesforce_push/drush.services.yml b/modules/salesforce_push/drush.services.yml
index c703cacbb313e23eac65209c4396e9afa5dbfe3c..6dd4337ea08ef1af71b39f10a292d89094deb5c3 100644
--- a/modules/salesforce_push/drush.services.yml
+++ b/modules/salesforce_push/drush.services.yml
@@ -1,6 +1,6 @@
 services:
-  salesforce_pull.commands:
+  salesforce_push.commands:
     class: \Drupal\salesforce_push\Commands\SalesforcePushCommands
     arguments: ['@salesforce.client', '@entity_type.manager', '@queue.salesforce_push', '@database']
     tags:
-    - { name: drush.command }
+      - { name: drush.command }
diff --git a/modules/salesforce_push/src/Commands/SalesforcePushCommands.php b/modules/salesforce_push/src/Commands/SalesforcePushCommands.php
index 829ddfee073c92c3965f8cb7b0b12416bfa94298..458fdb884e8c0fe637b748e62bbf3ed90e7be92d 100644
--- a/modules/salesforce_push/src/Commands/SalesforcePushCommands.php
+++ b/modules/salesforce_push/src/Commands/SalesforcePushCommands.php
@@ -4,7 +4,7 @@ namespace Drupal\salesforce_push\Commands;
 
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\salesforce\Commands\SalesforceCommandsBase;
+use Drupal\salesforce_mapping\Commands\SalesforceMappingCommandsBase;
 use Drupal\salesforce\Rest\RestClient;
 use Drupal\salesforce_push\PushQueue;
 use Symfony\Component\Console\Input\Input;
@@ -21,7 +21,7 @@ use Symfony\Component\Console\Output\Output;
  *   - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
  *   - http://cgit.drupalcode.org/devel/tree/drush.services.yml
  */
-class SalesforcePushCommands extends SalesforceCommandsBase {
+class SalesforcePushCommands extends SalesforceMappingCommandsBase {
 
   /**
    * Database service.
diff --git a/modules/salesforce_soap/salesforce_soap.info.yml b/modules/salesforce_soap/salesforce_soap.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1b24eb394125f5cdf91874ef412e4f19bf269686
--- /dev/null
+++ b/modules/salesforce_soap/salesforce_soap.info.yml
@@ -0,0 +1,8 @@
+name: Salesforce Soap
+type: module
+description: Exposes a SoapClient service for communicating with the Salesforce SOAP API.
+package: Salesforce
+core: 8.x
+
+dependencies:
+  - salesforce:salesforce
diff --git a/modules/salesforce_soap/salesforce_soap.services.yml b/modules/salesforce_soap/salesforce_soap.services.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3bf301f2887e09e0e6e9a78b75eb0acd255654b4
--- /dev/null
+++ b/modules/salesforce_soap/salesforce_soap.services.yml
@@ -0,0 +1,4 @@
+services:
+  salesforce.soap_client:
+    class: Drupal\salesforce_soap\Soap\SoapClient
+    arguments: ['@salesforce.client']
diff --git a/modules/salesforce_soap/src/Soap/SoapClient.php b/modules/salesforce_soap/src/Soap/SoapClient.php
new file mode 100644
index 0000000000000000000000000000000000000000..28dbae35a4b5f1c4e87f16e1c61f10eccc0fddd8
--- /dev/null
+++ b/modules/salesforce_soap/src/Soap/SoapClient.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Drupal\salesforce_soap\Soap;
+
+use Drupal\salesforce\Rest\RestClientInterface;
+use SforcePartnerClient;
+
+/**
+ * A client for communicating with the Salesforce SOAP API.
+ */
+class SoapClient extends SforcePartnerClient implements SoapClientInterface {
+
+  /**
+   * Indicates whether or not a successfull connection was made to the SOAP API.
+   *
+   * @var bool
+   */
+  protected $isConnected;
+
+  /**
+   * Salesforce REST API client.
+   *
+   * @var \Drupal\salesforce\Rest\RestClientInterface
+   */
+  protected $restApi;
+
+  /**
+   * Path to the WSDL that should be used.
+   *
+   * @var string
+   */
+  protected $wsdl;
+
+  /**
+   * Constructor which initializes the consumer.
+   *
+   * @param \Drupal\salesforce\Rest\RestClientInterface $rest_api
+   *   The Salesforce REST API client.
+   * @param string $wsdl
+   *   (Optional) Path to the WSDL that should be used.  Defaults to using the
+   *   partner WSDL from the developerforce/force.com-toolkit-for-php package.
+   */
+  public function __construct(RestClientInterface $rest_api, $wsdl = NULL) {
+    parent::__construct();
+
+    $this->restApi = $rest_api;
+
+    if ($wsdl) {
+      $this->wsdl = $wsdl;
+    }
+    else {
+      // Determine location of the developerforce/force.com-toolkit-for-php WSDL
+      // files.
+      $reflector = new \ReflectionClass('SforcePartnerClient');
+      $wsdl_dir = dirname($reflector->getFileName());
+      // Use the partner WSDL.
+      $this->wsdl = "$wsdl_dir/partner.wsdl.xml";
+    }
+
+    $this->connect();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function connect() {
+    $this->isConnected = FALSE;
+    // Use the "isAuthorized" callback to initialize session headers.
+    if ($this->restApi->isAuthorized()) {
+      $this->createConnection($this->wsdl);
+      $token = $this->restApi->getAccessToken();
+      if (!$token) {
+        $token = $this->restApi->refreshToken();
+      }
+      $this->setSessionHeader($token);
+      $this->setEndPoint($this->restApi->getApiEndPoint('partner'));
+      $this->isConnected = TRUE;
+    }
+    else {
+      throw new \Exception('Salesforce needs to be authorized to connect to this website.');
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isConnected() {
+    return $this->isConnected;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function trySoap($function, array $params = [], $refresh = FALSE) {
+    if ($refresh) {
+      $this->restApi->refreshToken();
+    }
+    if (!$this->isConnected) {
+      $this->connect();
+    }
+    try {
+      $results = call_user_func_array([$this, $function], $params);
+      return $results;
+    }
+    catch (SoapFault $e) {
+      // sf:INVALID_SESSION_ID is thrown on expired login (and other reasons).
+      // Our only recourse is to try refreshing our auth token. If we get any
+      // other exception, bubble it up.
+      if ($e->faultcode != 'sf:INVALID_SESSION_ID') {
+        throw $e;
+      }
+
+      // If we didn't already try it, refresh the access token and try the call
+      // again.
+      if (!$refresh) {
+        return $this->trySoap($function, $params, TRUE);
+      }
+      else {
+        // Our connection is not working.
+        $this->isConnected = FALSE;
+        throw $e;
+      }
+
+    }
+  }
+
+}
diff --git a/modules/salesforce_soap/src/Soap/SoapClientInterface.php b/modules/salesforce_soap/src/Soap/SoapClientInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..7eb6ee96497d19eeb718c700a2ea7dd7275dfcfb
--- /dev/null
+++ b/modules/salesforce_soap/src/Soap/SoapClientInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Drupal\salesforce_soap\Soap;
+
+/**
+ * A client for communicating with the Salesforce SOAP API.
+ */
+interface SoapClientInterface {
+
+  /**
+   * Establish a connection to the SOAP API.
+   */
+  public function connect();
+
+  /**
+   * Whether or not this client is connected to the SOAP API.
+   */
+  public function isConnected();
+
+  /**
+   * Salesforce SOAP API resource wrapper.
+   *
+   * Ensures the connection is established with the SOAP API prior to making the
+   * call and automatically attempts a re-auth when the API responds with
+   * invalid session ID / access token.
+   *
+   * @param string $function
+   *   The name of the SOAP API function to attempt.
+   * @param array $params
+   *   (Optional) An array of parameters to pass through to the function.
+   * @param bool $refresh
+   *   (Optional) Refresh the access token prior to making the call.  Defaults
+   *   to FALSE, in which case a refresh is only attempted if the API responds
+   *   invalid session ID / access token.
+   *
+   * @return mixed
+   *   The return value from $function.
+   *
+   * @see \SforcePartnerClient
+   */
+  public function trySoap($function, array $params = [], $refresh = FALSE);
+
+}
diff --git a/src/Commands/SalesforceCommands.php b/src/Commands/SalesforceCommands.php
index 8ca48d6bdc4e2ad4c88fc95e0e29678fb51e80cd..22fb0df284453e207892a8f234df49ce7a13db07 100644
--- a/src/Commands/SalesforceCommands.php
+++ b/src/Commands/SalesforceCommands.php
@@ -595,7 +595,7 @@ class SalesforceCommands extends SalesforceCommandsBase {
    * @return \Drupal\salesforce\Commands\QueryResult
    *   The query result.
    *
-   * @command salesforcef:query-object
+   * @command salesforce:query-object
    * @aliases sfqo,sf-query-object
    */
   public function queryObject($object, array $options = [
diff --git a/src/Commands/SalesforceCommandsBase.php b/src/Commands/SalesforceCommandsBase.php
index 243e6814cda8e665445381b4da48bd8ecb54d5f1..79403e882727813dc21f526e2728095cd8cde8b9 100644
--- a/src/Commands/SalesforceCommandsBase.php
+++ b/src/Commands/SalesforceCommandsBase.php
@@ -29,20 +29,6 @@ abstract class SalesforceCommandsBase extends DrushCommands {
    */
   protected $etm;
 
-  /**
-   * Salesforce Mapping storage handler.
-   *
-   * @var \Drupal\salesforce_mapping\SalesforceMappingStorage
-   */
-  protected $mappingStorage;
-
-  /**
-   * Mapped Object storage handler.
-   *
-   * @var \Drupal\salesforce_mapping\MappedObjectStorage
-   */
-  protected $mappedObjectStorage;
-
   /**
    * SalesforceCommandsBase constructor.
    *
@@ -57,8 +43,6 @@ abstract class SalesforceCommandsBase extends DrushCommands {
   public function __construct(RestClient $client, EntityTypeManagerInterface $etm) {
     $this->client = $client;
     $this->etm = $etm;
-    $this->mappingStorage = $etm->getStorage('salesforce_mapping');
-    $this->mappedObjectStorage = $etm->getStorage('salesforce_mapped_object');
   }
 
   /**
@@ -77,142 +61,6 @@ abstract class SalesforceCommandsBase extends DrushCommands {
     }
   }
 
-  /**
-   * Collect a salesforce mapping interactively.
-   */
-  protected function interactMapping(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE, $dir = NULL) {
-    if ($name = $input->getArgument('name')) {
-      if (strtoupper($name) == 'ALL') {
-        $input->setArgument('name', 'ALL');
-        return;
-      }
-      /** @var \Drupal\salesforce_mapping\Entity\SalesforceMapping $mapping */
-      $mapping = $this->mappingStorage->load($name);
-      if (!$mapping) {
-        $this->logger()->error(dt('Mapping %name does not exist.', ['%name' => $name]));
-      }
-      elseif ($dir == 'push' && !$mapping->doesPush()) {
-        $this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
-      }
-      elseif ($dir == 'pull' && !$mapping->doesPull()) {
-        $this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
-      }
-      else {
-        return;
-      }
-    }
-    if ($dir == 'pull') {
-      $options = $this->mappingStorage->loadPullMappings();
-    }
-    elseif ($dir == 'push') {
-      $options = $this->mappingStorage->loadPushMappings();
-    }
-    else {
-      $options = $this->mappingStorage->loadMultiple();
-    }
-    $this->doMappingNameOptions($input, array_keys($options), $message, $allOption);
-
-  }
-
-  /**
-   * Collect a salesforce mapping name, and set it to a "name" argument.
-   */
-  protected function interactPushMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
-    return $this->interactMapping($input, $output, $message, $allOption, 'push');
-  }
-
-  /**
-   * Collect a salesforce mapping name, and set it to a "name" argument.
-   */
-  protected function interactPullMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
-    return $this->interactMapping($input, $output, $message, $allOption, 'pull');
-  }
-
-  /**
-   * Helper method to collect the choice from user, given a set of options.
-   */
-  protected function doMappingNameOptions(Input $input, array $options, $message, $allOption = FALSE) {
-    $options = array_combine($options, $options);
-    if ($allOption) {
-      $options['ALL'] = $allOption;
-    }
-    if (!$answer = $this->io()->choice($message, $options)) {
-      throw new UserAbortException();
-    }
-    $input->setArgument('name', $answer);
-  }
-
-  /**
-   * Given a mapping name (and optional direction), get an array of mappings.
-   *
-   * @param string $name
-   *   'ALL' to load all mappings, or a mapping id.
-   * @param string $dir
-   *   'push'|'pull'|NULL to load limit mappings by push or pull types.
-   *
-   * @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
-   *   The mappings.
-   */
-  protected function getMappingsFromName($name, $dir = NULL) {
-    $mappings = [];
-    if ($name == 'ALL') {
-      if ($dir == 'pull') {
-        $mappings = $this->mappingStorage->loadPullMappings();
-      }
-      elseif ($dir == 'push') {
-        $mappings = $this->mappingStorage->loadPushMappings();
-      }
-      else {
-        $mappings = $this->mappingStorage->loadMultiple();
-      }
-    }
-    else {
-      $mapping = $this->mappingStorage->load($name);
-      if ($dir == 'push' && !$mapping->doesPush()) {
-        throw new \Exception(dt("Mapping !name does not push.", ['!name' => $name]));
-      }
-      elseif ($dir == 'pull' && !$mapping->doesPull()) {
-        throw new \Exception(dt("Mapping !name does not pull.", ['!name' => $name]));
-      }
-      $mappings = [$mapping];
-    }
-    $mappings = array_filter($mappings);
-    if (empty($mappings)) {
-      throw new \Exception(dt('No push mappings loaded'));
-    }
-    return $mappings;
-  }
-
-  /**
-   * Given a mapping name, get an array of matching push mappings.
-   *
-   * @param string $name
-   *   The mapping name.
-   *
-   * @return \Drupal\salesforce_mapping\Entity\SalesforceMapping[]
-   *   The matching mappings.
-   *
-   * @throws \Exception
-   */
-  protected function getPushMappingsFromName($name) {
-    return $this->getMappingsFromName($name, 'push');
-  }
-
-  /**
-   * Given a mappin gname, get an array of matching pull mappings.
-   *
-   * @param string $name
-   *   The mapping name.
-   *
-   * @return \Drupal\salesforce_mapping\Entity\SalesforceMapping[]
-   *   The pull mappings.
-   *
-   * @throws \Exception
-   */
-  protected function getPullMappingsFromName($name) {
-    return $this->getMappingsFromName($name, 'pull');
-  }
-
   /**
    * Pass-through helper to add appropriate formatters for a query result.
    *
diff --git a/src/Rest/RestClient.php b/src/Rest/RestClient.php
index 14122ab54e8894a4aa9ad16ea8a0aa4d2d9a1977..c24c237bb8a94a53b21cbaacc8e283d8cb4233af 100644
--- a/src/Rest/RestClient.php
+++ b/src/Rest/RestClient.php
@@ -854,10 +854,10 @@ class RestClient implements RestClientInterface {
    */
   public function getRecordTypeIdByDeveloperName($name, $devname, $reset = FALSE) {
     $record_types = $this->getRecordTypes($name, $reset);
-    if (empty($record_types[$name][$devname])) {
+    if (empty($record_types[$devname])) {
       throw new \Exception("No record type $devname for $name");
     }
-    return $record_types[$name][$devname]->id();
+    return $record_types[$devname]->id();
   }
 
   /**