diff --git a/docs/src/pages/guides/FHIRServerUsersGuide.md b/docs/src/pages/guides/FHIRServerUsersGuide.md
index f07953eb7f7..3f349697a86 100644
--- a/docs/src/pages/guides/FHIRServerUsersGuide.md
+++ b/docs/src/pages/guides/FHIRServerUsersGuide.md
@@ -1476,7 +1476,7 @@ The Bulk Data web application writes the exported FHIR resources to an IBM Cloud
             "useServerTruststore": true
         },
         "pageSize": 100,
-        "batchIdEncryptionKey": "example-password",
+        "batchIdEncodingKey": "example-password",
         "maxPartitions": 3,
         "maxInputs": 5
     },
@@ -2356,7 +2356,7 @@ This section contains reference information about each of the configuration prop
 |`fhirServer/bulkdata/core/file/resourceCountThreshold`|number|The number of resources at which to finish writing a given file. The actual number of resources written to a single file may be slightly above this number, dependent on the configured page size. Use `0` to indicate that there is no limit to the number of resources to be written to a single file.|
 |`fhirServer/bulkdata/core/azure/objectSizeThresholdMB`|number|The size, in megabytes, at which to finish writing a given object.|
 |`fhirServer/bulkdata/core/azure/objectResourceCountThreshold`|number|The number of resources at which to finish writing a given object. The actual number of resources written to a single object may be slightly above this number, dependent on the configured page size.|
-|`fhirServer/bulkdata/core/batchIdEncryptionKey`|string|Encoding key for JavaBatch job id |
+|`fhirServer/bulkdata/core/batchIdEncodingKey`|string|Encoding key for JavaBatch job id |
 |`fhirServer/bulkdata/core/pageSize`|number|The search page size for patient/group export and the legacy export, the default value is 1000 |
 |`fhirServer/bulkdata/core/maxPartitions`|number| The maximum number of simultaneous partitions that are processed per Export and Import |
 |`fhirServer/bulkdata/core/maxInputs`|number| The number of inputs allowed for $import |
@@ -2535,6 +2535,7 @@ This section contains reference information about each of the configuration prop
 |`fhirServer/bulkdata/core/cos/presignedExpiry`|86400|
 |`fhirServer/bulkdata/core/azure/objectSizeThresholdMB`|200|
 |`fhirServer/bulkdata/core/azure/objectResourceCountThreshold`|200000|
+|`fhirServer/bulkdata/core/batchIdEncodingKey`|""|
 |`fhirServer/bulkdata/core/pageSize`|1000|
 |`fhirServer/bulkdata/core/maxPartitions`|5|
 |`fhirServer/bulkdata/core/maxInputs`|5|
@@ -2717,7 +2718,7 @@ Cases where that behavior is not supported are marked below with an `N` in the `
 |`fhirServer/bulkdata/core/cos/presignedExpiry`|Y|Y|Y|
 |`fhirServer/bulkdata/core/azure/objectSizeThresholdMB`|N|N||
 |`fhirServer/bulkdata/core/azure/objectResourceCountThreshold`|N|N||
-|`fhirServer/bulkdata/core/batchIdEncryptionKey`|Y|N|Y|
+|`fhirServer/bulkdata/core/batchIdEncodingKey`|Y|N|Y|
 |`fhirServer/bulkdata/core/pageSize`|Y|Y|Y|
 |`fhirServer/bulkdata/core/maxPartitions`|Y|Y|Y|
 |`fhirServer/bulkdata/core/maxInputs`|Y|Y|Y|
diff --git a/docs/src/pages/guides/FHIRValidationGuide.md b/docs/src/pages/guides/FHIRValidationGuide.md
index a3989837051..35e82a2e722 100644
--- a/docs/src/pages/guides/FHIRValidationGuide.md
+++ b/docs/src/pages/guides/FHIRValidationGuide.md
@@ -219,7 +219,7 @@ Below is the list of implementation guides that are packaged as part of the proj
 |--------------------|-----------------|
 |US Core|`3.1.1`, `4.0.0`, `5.0.1`|
 |CARIN Consumer Directed Payer Data Exchange (CARIN IG for BlueButton®)|`1.0.0`, `1.1.0`|
-|minimal Common Oncology Data Elements (mCODE)|`1.0.0`
+|minimal Common Oncology Data Elements (mCODE)|`1.0.0`|
 |Da Vinci Health Record Exchange (HREX)|`1.0.0`|
 |Da Vinci Payer Data Exchange (PDEX)|`1.0.0`, `2.0.0`|
 |Da Vinci Payer Data Exchange (PDEX) Plan Net|`1.0.0`, `1.1.0`|
diff --git a/fhir-parent/pom.xml b/fhir-parent/pom.xml
index 4208aa62b32..98a1c230608 100644
--- a/fhir-parent/pom.xml
+++ b/fhir-parent/pom.xml
@@ -726,6 +726,11 @@
                 <artifactId>icu4j</artifactId>
                 <version>71.1</version>
             </dependency>
+            <dependency>
+                <groupId>org.hashids</groupId>
+                <artifactId>hashids</artifactId>
+                <version>1.0.3</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json
index 3fa58e72b70..27cb4e457b6 100644
--- a/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json
+++ b/fhir-server-webapp/src/main/liberty/config/config/default/fhir-server-config.json
@@ -156,7 +156,7 @@
                     "resourceCountThreshold": 200000
                 },
                 "pageSize": 100,
-                "batchIdEncryptionKey": "change-password",
+                "batchIdEncodingKey": "change-password",
                 "maxPartitions": 5,
                 "maxInputs": 5,
                 "maxChunkReadTime": "90000",
diff --git a/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-azurite.json b/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-azurite.json
index 37813b9bffe..22a03e4a643 100644
--- a/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-azurite.json
+++ b/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-azurite.json
@@ -340,7 +340,7 @@
           "resourceCountThreshold": 200000
         },
         "pageSize": 100,
-        "batchIdEncryptionKey": "change-password",
+        "batchIdEncodingKey": "change-password",
         "maxPartitions": 5,
         "maxInputs": 5
       },
diff --git a/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-minio.json b/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-minio.json
index d009481f7a0..149c5c8d8b7 100644
--- a/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-minio.json
+++ b/fhir-server-webapp/src/test/liberty/config/config/default/fhir-server-config-postgresql-minio.json
@@ -330,7 +330,7 @@
           "resourceCountThreshold": 200000
         },
         "pageSize": 100,
-        "batchIdEncryptionKey": "change-password",
+        "batchIdEncodingKey": "change-password",
         "maxPartitions": 5,
         "maxInputs": 5
       },
diff --git a/operation/fhir-operation-bulkdata/pom.xml b/operation/fhir-operation-bulkdata/pom.xml
index 237c454f03f..1847a9ad529 100644
--- a/operation/fhir-operation-bulkdata/pom.xml
+++ b/operation/fhir-operation-bulkdata/pom.xml
@@ -19,6 +19,18 @@
             <artifactId>fhir-server</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hashids</groupId>
+            <artifactId>hashids</artifactId>
+        </dependency>
         <dependency>
             <groupId>jakarta.ws.rs</groupId>
             <artifactId>jakarta.ws.rs-api</artifactId>
@@ -34,14 +46,6 @@
             <artifactId>jsonassert</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpcore</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-frontend-jaxrs</artifactId>
diff --git a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/client/BulkDataClient.java b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/client/BulkDataClient.java
index 4db2e54e26c..9a7bab445a4 100644
--- a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/client/BulkDataClient.java
+++ b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/client/BulkDataClient.java
@@ -39,7 +39,6 @@
 import org.apache.http.impl.client.BasicResponseHandler;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.util.EntityUtils;
-
 import org.linuxforhealth.fhir.config.FHIRRequestContext;
 import org.linuxforhealth.fhir.exception.FHIROperationException;
 import org.linuxforhealth.fhir.model.generator.exception.FHIRGeneratorException;
@@ -55,7 +54,6 @@
 import org.linuxforhealth.fhir.operation.bulkdata.model.JobInstanceRequest;
 import org.linuxforhealth.fhir.operation.bulkdata.model.JobInstanceResponse;
 import org.linuxforhealth.fhir.operation.bulkdata.model.PollingLocationResponse;
-import org.linuxforhealth.fhir.operation.bulkdata.model.transformer.JobIdEncodingTransformer;
 import org.linuxforhealth.fhir.operation.bulkdata.model.type.Input;
 import org.linuxforhealth.fhir.operation.bulkdata.model.type.JobParameter;
 import org.linuxforhealth.fhir.operation.bulkdata.model.type.JobType;
@@ -63,6 +61,7 @@
 import org.linuxforhealth.fhir.operation.bulkdata.model.type.StorageType;
 import org.linuxforhealth.fhir.operation.bulkdata.model.url.DownloadUrl;
 import org.linuxforhealth.fhir.operation.bulkdata.util.BulkDataExportUtil;
+import org.linuxforhealth.fhir.operation.bulkdata.util.CommonUtil;
 
 /**
  * BulkData Client to connect to the other server.
@@ -227,7 +226,7 @@ public String submitExport(Instant since, Set<String> types, ExportType exportTy
         CloseableHttpResponse jobResponse = cli.execute(jobPost);
 
         int status = -1;
-        String jobId = "-1";
+        int jobId = -1;
         try {
             status = jobResponse.getStatusLine().getStatusCode();
             handleStandardResponseStatus(status);
@@ -243,7 +242,7 @@ public String submitExport(Instant since, Set<String> types, ExportType exportTy
             String responseString = new BasicResponseHandler().handleResponse(jobResponse);
             JobInstanceResponse response = JobInstanceResponse.Parser.parse(responseString);
 
-            jobId = Integer.toString(response.getInstanceId());
+            jobId = response.getInstanceId();
 
         } finally {
             jobPost.releaseConnection();
@@ -251,7 +250,7 @@ public String submitExport(Instant since, Set<String> types, ExportType exportTy
         }
         cli.close();
 
-        return baseUri + "/$bulkdata-status?job=" + JobIdEncodingTransformer.getInstance().encodeJobId(jobId);
+        return baseUri + "/$bulkdata-status?job=" + CommonUtil.encodeJobId(jobId);
     }
 
     /**
@@ -663,7 +662,7 @@ public String submitImport(String inputFormat, String inputSource, List<Input> i
         CloseableHttpResponse jobResponse = cli.execute(jobPost);
 
         int status = -1;
-        String jobId = "-1";
+        int jobId = -1;
         try {
             status = jobResponse.getStatusLine().getStatusCode();
             handleStandardResponseStatus(status);
@@ -682,7 +681,7 @@ public String submitImport(String inputFormat, String inputSource, List<Input> i
 
             JobInstanceResponse response = JobInstanceResponse.Parser.parse(responseString);
 
-            jobId = Integer.toString(response.getInstanceId());
+            jobId = response.getInstanceId();
 
         } finally {
             jobPost.releaseConnection();
@@ -690,7 +689,7 @@ public String submitImport(String inputFormat, String inputSource, List<Input> i
         }
         cli.close();
 
-        return baseUri + "/$bulkdata-status?job=" + JobIdEncodingTransformer.getInstance().encodeJobId(jobId);
+        return baseUri + "/$bulkdata-status?job=" + CommonUtil.encodeJobId(jobId);
     }
 
     /**
diff --git a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/ConfigurationAdapter.java b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/ConfigurationAdapter.java
index 5985f816a68..9dd7deb87ea 100644
--- a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/ConfigurationAdapter.java
+++ b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/ConfigurationAdapter.java
@@ -215,13 +215,13 @@ public interface ConfigurationAdapter {
     int getCorePageSize();
 
     /**
-     * get core batch id encryption key for the job id that is returned
+     * get core batch id encoding key for the job id that is returned
      *
      * @implNote System value. We want to minimize the conflict possiblity.
      *
      * @return
      */
-    String getCoreBatchIdEncryptionKey();
+    String getCoreBatchIdEncodingKey();
 
     /**
      * get core max partitions
@@ -557,10 +557,10 @@ default boolean isStorageProviderParquetEnabled(String provider) {
     boolean getStorageProviderUsesRequestAccessToken(String provider);
 
     /**
-     * allows multiple resources in a single file. 
-     * 
-     * @implNote this default is false. 
-     * 
+     * allows multiple resources in a single file.
+     *
+     * @implNote this default is false.
+     *
      * @param source
      * @return
      */
diff --git a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/impl/AbstractSystemConfigurationImpl.java b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/impl/AbstractSystemConfigurationImpl.java
index d2ac8e9247d..7c94679366a 100644
--- a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/impl/AbstractSystemConfigurationImpl.java
+++ b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/config/impl/AbstractSystemConfigurationImpl.java
@@ -107,8 +107,8 @@ private static final int defaultCoreMaxParititions() {
     }
 
     @Override
-    public String getCoreBatchIdEncryptionKey() {
-        return FHIRConfigHelper.getStringProperty("fhirServer/bulkdata/core/batchIdEncryptionKey", null);
+    public String getCoreBatchIdEncodingKey() {
+        return FHIRConfigHelper.getStringProperty("fhirServer/bulkdata/core/batchIdEncodingKey", "");
     }
 
     @Override
@@ -403,7 +403,7 @@ public String getStorageProviderAuthTypeConnectionString(String provider) {
 
     @Override
     public String getProviderAzureServiceVersion(String provider) {
-        return FHIRConfigHelper.getStringProperty("fhirServer/bulkdata/storageProviders/" + provider + "/serviceVersion", null);        
+        return FHIRConfigHelper.getStringProperty("fhirServer/bulkdata/storageProviders/" + provider + "/serviceVersion", null);
     }
 
     @Override
diff --git a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/model/transformer/JobIdEncodingTransformer.java b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/model/transformer/JobIdEncodingTransformer.java
deleted file mode 100644
index f28279f8df7..00000000000
--- a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/model/transformer/JobIdEncodingTransformer.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * (C) Copyright IBM Corp. 2021
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package org.linuxforhealth.fhir.operation.bulkdata.model.transformer;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.linuxforhealth.fhir.config.FHIRRequestContext;
-import org.linuxforhealth.fhir.operation.bulkdata.config.ConfigurationFactory;
-
-/**
- * Manages the Job Id Encryption.
- */
-public class JobIdEncodingTransformer {
-
-    private static final String CLASSNAME = JobIdEncodingTransformer.class.getName();
-    private static final Logger logger = Logger.getLogger(CLASSNAME);
-
-    // Tenant Encryption key used for JavaBatch Job ID
-    private static ConcurrentMap<String, SecretKeySpec> KEY_MAP = new ConcurrentHashMap<>();
-
-    private static JobIdEncodingTransformer transformer = null;
-
-    private JobIdEncodingTransformer() {
-        // No Operation
-    }
-
-    /**
-     * get the instance
-     *
-     * @return
-     */
-    public static JobIdEncodingTransformer getInstance() {
-        if (transformer == null) {
-            transformer = new JobIdEncodingTransformer();
-        }
-        return transformer;
-    }
-
-    /*
-     * gets the tenant specific encryption key.
-     * @return
-     */
-    private SecretKeySpec getJobIdEncryptionKey() {
-        String encryptionKey = ConfigurationFactory.getInstance().getCoreBatchIdEncryptionKey();
-        SecretKeySpec secretKey = null;
-
-        if (encryptionKey != null && !encryptionKey.isEmpty()) {
-            try {
-                byte[] keyBytes = encryptionKey.getBytes("UTF-8");
-                keyBytes = Arrays.copyOf(MessageDigest.getInstance("SHA-1").digest(keyBytes), 16);
-                secretKey = new SecretKeySpec(keyBytes, "AES");
-            } catch (Exception e) {
-                logger.log(Level.WARNING, "Fail to generate encryption key from config!", e);
-            }
-        }
-
-        if (secretKey == null) {
-            logger.warning("Failed to get encryption key, JavaBatch Job ids will not be encrypted!");
-        }
-        return secretKey;
-    }
-
-    /**
-     * encodes the job id
-     *
-     * @implNote note a Cipher is used here, however it is not used to encrypt sensitive information rather encode the jobId.
-     *
-     * @param jobId
-     * @return
-     */
-    public String encodeJobId(String jobId) {
-        String tenantId = FHIRRequestContext.get().getTenantId();
-        SecretKeySpec key = KEY_MAP.computeIfAbsent(tenantId, k -> getJobIdEncryptionKey());
-        // Encrypt and UrlEncode the batch job id.
-        if (key == null) {
-            return jobId;
-        } else {
-            try {
-                // Use light weight encryption without salt to simplify both the encryption/decryption and also config.
-                Cipher cp = Cipher.getInstance("AES/ECB/PKCS5Padding");
-                cp.init(Cipher.ENCRYPT_MODE, key);
-
-                // Encrypt the job id, base64-encode it, and replace all `/` chars with the less problematic `_` char
-                String encodedJobId = Base64.getEncoder().withoutPadding().encodeToString(cp.doFinal(jobId.getBytes("UTF-8"))).replaceAll("/", "_");
-                // The encrypted job id is used in the polling content location url directly, so urlencode here.
-                return java.net.URLEncoder.encode(encodedJobId, StandardCharsets.UTF_8.name());
-            } catch (Exception e) {
-                return jobId;
-            }
-        }
-    }
-
-    /**
-     * decodes the job id.
-     *
-     * @implNote note a Cipher is used here, however it is not used to encrypt sensitive information rather encode the
-     *           jobId.
-     *
-     * @param encodedJobId
-     * @return
-     */
-    public String decodeJobId(String encodedJobId) {
-        String tenantId = FHIRRequestContext.get().getTenantId();
-        SecretKeySpec key = KEY_MAP.computeIfAbsent(tenantId, k -> getJobIdEncryptionKey());
-        // Decrypt to get the batch job id.
-        if (key == null) {
-            return encodedJobId;
-        } else {
-            try {
-                // Use light weight encryption without salt to simplify both the encryption/decryption and also config.
-                Cipher cp = Cipher.getInstance("AES/ECB/PKCS5PADDING");
-                cp.init(Cipher.DECRYPT_MODE, key);
-                // The encrypted job id has already been urldecoded by liberty runtime before reaching this function,
-                // so, we don't do urldecode here.)
-                return new String(cp.doFinal(Base64.getDecoder().decode(encodedJobId.replaceAll("_", "/"))), "UTF-8");
-            } catch (Exception e) {
-                return encodedJobId;
-            }
-        }
-    }
-}
diff --git a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtil.java b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtil.java
index 9174319f427..4eb03da41bd 100644
--- a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtil.java
+++ b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtil.java
@@ -18,8 +18,6 @@
 
 import javax.ws.rs.core.MediaType;
 
-import org.owasp.encoder.Encode;
-
 import org.linuxforhealth.fhir.config.FHIRConfigHelper;
 import org.linuxforhealth.fhir.core.FHIRMediaType;
 import org.linuxforhealth.fhir.core.FHIRVersionParam;
@@ -34,9 +32,9 @@
 import org.linuxforhealth.fhir.operation.bulkdata.OperationConstants;
 import org.linuxforhealth.fhir.operation.bulkdata.OperationConstants.ExportType;
 import org.linuxforhealth.fhir.operation.bulkdata.model.PollingLocationResponse;
-import org.linuxforhealth.fhir.operation.bulkdata.model.transformer.JobIdEncodingTransformer;
 import org.linuxforhealth.fhir.search.compartment.CompartmentHelper;
 import org.linuxforhealth.fhir.server.spi.operation.FHIROperationContext;
+import org.owasp.encoder.Encode;
 
 /**
  * BulkData Util captures common methods
@@ -319,15 +317,14 @@ public String checkAndValidateJob(Parameters parameters) throws FHIROperationExc
         if (parameters != null) {
             for (Parameters.Parameter parameter : parameters.getParameter()) {
                 if (OperationConstants.PARAM_JOB.equals(parameter.getName().getValue())
-                        && parameter.getValue() != null && parameter.getValue().is(org.linuxforhealth.fhir.model.type.String.class)) {
-                    String job = JobIdEncodingTransformer.getInstance().decodeJobId(parameter.getValue().as(org.linuxforhealth.fhir.model.type.String.class).getValue());
-
-                    // The job is never going to be empty or null as STRING is never empty at this point.
-                    if (job.contains("/") || job.contains("?")) {
-                        throw new FHIROperationException("job passed is invalid and is not supported");
+                        && parameter.getValue() != null && parameter.getValue().is(FHIR_STRING)) {
+                    try {
+                        // Don't look at any other parameters.
+                        return CommonUtil.decodeJobId(parameter.getValue().as(FHIR_STRING).getValue());
+                    } catch(IllegalArgumentException e) {
+                        String msg = "invalid job id was passed";
+                        throw buildOperationException(msg, IssueType.INVALID, e);
                     }
-                    // Don't look at any other parameters.
-                    return job;
                 }
             }
         }
diff --git a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/CommonUtil.java b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/CommonUtil.java
index b75ecb43c72..bc6c22b04c1 100644
--- a/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/CommonUtil.java
+++ b/operation/fhir-operation-bulkdata/src/main/java/org/linuxforhealth/fhir/operation/bulkdata/util/CommonUtil.java
@@ -1,11 +1,12 @@
 /*
- * (C) Copyright IBM Corp. 2019, 2021
+ * (C) Copyright IBM Corp. 2019, 2022
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 
 package org.linuxforhealth.fhir.operation.bulkdata.util;
 
+import org.hashids.Hashids;
 import org.linuxforhealth.fhir.config.FHIRRequestContext;
 import org.linuxforhealth.fhir.exception.FHIROperationException;
 import org.linuxforhealth.fhir.model.resource.OperationOutcome;
@@ -21,6 +22,8 @@
  * Common Util captures common methods
  */
 public class CommonUtil {
+    // min length constant for the "Hashids" we use to obfuscate job ids
+    private static final int HASHID_MIN_LENGTH = 6;
 
     /**
      * Type of Operation Call
@@ -115,14 +118,73 @@ public void verifyAllowedType(String storageType) throws FHIROperationException
         }
     }
 
-    public static FHIROperationException buildExceptionWithIssue(String msg, IssueType issueType)
-        throws FHIROperationException {
+    /**
+     * encode the job id as a short string for use in URLs
+     *
+     * @param jobId the numeric job id to encode
+     * @return
+     * @implNote The implementation uses the tenantId from the request context and the
+     *          corresponding coreBatchIdEncodingKey from fhir-server-config as a seed for
+     *          the encoding.
+     */
+    public static String encodeJobId(long jobId) {
+        Hashids encoder = getHashids();
+        return encoder.encode(jobId);
+    }
+
+    /**
+     * decode the job id back into the string representation of its numeric job id
+     *
+     * @param encodedJobId a job id encoded via {@link #encodeJobId(long, String, String)}
+     * @return
+     * @throws IllegalArgumentException if the passed encodedJobId could not be decoded
+     * @implNote The implementation uses the tenantId from the request context and the
+     *          corresponding coreBatchIdEncodingKey from fhir-server-config to decode.
+     */
+    public static String decodeJobId(String encodedJobId) {
+        Hashids decoder = getHashids();
+        long[] decodedArray = decoder.decode(encodedJobId);
+        if (decodedArray.length != 1) {
+            throw new IllegalArgumentException("expected an encodedJobId with a single part, but found " + decodedArray.length);
+        }
+        return Long.toString(decodedArray[0]);
+    }
+
+    /**
+     * Get the tenantId from the request context and the corresponding coreBatchIdEncodingKey from
+     * fhir-server-config and use that as the seed for the returned Hashids
+     */
+    private static Hashids getHashids() {
+        String configSecret = ConfigurationFactory.getInstance().getCoreBatchIdEncodingKey();
+        String seed = FHIRRequestContext.get().getTenantId() + ":" + configSecret;
+        return new Hashids(seed, HASHID_MIN_LENGTH);
+    }
+
+    /**
+     * Construct a FHIROperationException with the passed {@code msg} and
+     * a single OperationOutcome.Issue of type {@code issueType}
+     *
+     * @param msg
+     * @param issueType
+     * @return
+     * @throws FHIROperationException
+     */
+    public static FHIROperationException buildExceptionWithIssue(String msg, IssueType issueType) {
         OperationOutcome.Issue ooi = FHIRUtil.buildOperationOutcomeIssue(msg, issueType);
         return new FHIROperationException(msg).withIssue(ooi);
     }
 
-    public static FHIROperationException buildExceptionWithIssue(String msg, Throwable cause, IssueType issueType)
-        throws FHIROperationException {
+    /**
+     * Construct a FHIROperationException with the passed {@code msg}, caused by (@code cause}, and
+     * a single OperationOutcome.Issue of type {@code issueType}
+     *
+     * @param msg
+     * @param cause
+     * @param issueType
+     * @return
+     * @throws FHIROperationException
+     */
+    public static FHIROperationException buildExceptionWithIssue(String msg, Throwable cause, IssueType issueType) {
         OperationOutcome.Issue ooi = FHIRUtil.buildOperationOutcomeIssue(msg, issueType);
         return new FHIROperationException(msg, cause).withIssue(ooi);
     }
diff --git a/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/model/transformer/JobIdEncodingTransformerTest.java b/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/model/transformer/JobIdEncodingTransformerTest.java
deleted file mode 100644
index e7d763557f0..00000000000
--- a/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/model/transformer/JobIdEncodingTransformerTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * (C) Copyright IBM Corp. 2021, 2022
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package org.linuxforhealth.fhir.operation.bulkdata.model.transformer;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-
-import java.lang.reflect.Method;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import org.linuxforhealth.fhir.config.FHIRConfiguration;
-import org.linuxforhealth.fhir.config.FHIRRequestContext;
-import org.linuxforhealth.fhir.exception.FHIRException;
-
-/**
- * Tests the Job ID Encoding Transformer.
- */
-public class JobIdEncodingTransformerTest {
-
-    @BeforeClass
-    public void setup() {
-        FHIRConfiguration.setConfigHome("target/test-classes");
-    }
-
-    @BeforeMethod
-    public void startMethod(Method method) throws FHIRException {
-
-        // Configure the request context for our search tests
-        FHIRRequestContext context = FHIRRequestContext.get();
-        context.setTenantId("default");
-    }
-
-    @AfterMethod
-    public void clearThreadLocal() {
-        FHIRRequestContext.remove();
-    }
-
-    @Test
-    public void testTransformerRoundTrip() throws Exception {
-        // Using the legacy implementation for the configuration the encode/decode uses change-password
-        final JobIdEncodingTransformer transformer = JobIdEncodingTransformer.getInstance();
-
-        String jobId = transformer.decodeJobId("1");
-        assertNotNull(jobId);
-        assertEquals(jobId, "1");
-
-        // This results in at least one case where the naive base64 encoding of the encoded jobId would
-        // 1. have a leading '/' which is prohibited by the S3 client; and
-        // 2. have consecutive '/' which can makes it harder to get
-        for (int i = 0; i < 2000; i++) {
-            jobId = String.valueOf(i);
-
-            String encodedJobId = transformer.encodeJobId(jobId);
-            assertNotNull(encodedJobId);
-            assertFalse(encodedJobId.equals(jobId));
-            assertFalse(encodedJobId.startsWith("/"));
-            assertFalse(encodedJobId.contains("//"));
-
-            encodedJobId = URLDecoder.decode(encodedJobId, StandardCharsets.UTF_8.toString());
-            assertNotNull(encodedJobId);
-
-            String decodedJobId = transformer.decodeJobId(encodedJobId);
-            assertNotNull(decodedJobId);
-            assertEquals(decodedJobId, jobId);
-        }
-    }
-}
\ No newline at end of file
diff --git a/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataCommonUtilTest.java b/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataCommonUtilTest.java
new file mode 100644
index 00000000000..dc1a2c9b09a
--- /dev/null
+++ b/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataCommonUtilTest.java
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright IBM Corp. 2021, 2022
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.linuxforhealth.fhir.operation.bulkdata.util;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.lang.reflect.Method;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.linuxforhealth.fhir.config.FHIRRequestContext;
+import org.linuxforhealth.fhir.exception.FHIRException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests the Job ID Encoding Transformer.
+ */
+public class BulkDataCommonUtilTest {
+    @BeforeMethod
+    public void startMethod(Method method) throws FHIRException {
+
+        // Configure the request context for our search tests
+        FHIRRequestContext context = FHIRRequestContext.get();
+        context.setTenantId("default");
+    }
+
+    @AfterMethod
+    public void clearThreadLocal() {
+        FHIRRequestContext.remove();
+    }
+
+    @Test
+    public void testJobIdEncodingRoundTrip() throws Exception {
+        Set<String> encodedIds = new HashSet<>();
+        for (int i = 0; i < Math.pow(10, 5); i++) {
+            String jobId = String.valueOf(i);
+
+            String encodedJobId = CommonUtil.encodeJobId(i);
+            assertNotNull(encodedJobId);
+            assertFalse(encodedJobId.equals(jobId));
+            assertFalse(encodedJobId.contains("/"), "can't contain a slash");
+            assertTrue(encodedIds.add(encodedJobId), "each encoded id must be unique");
+
+            // Ensure all the chars are URL-safe
+            assertEquals(encodedJobId, URLDecoder.decode(encodedJobId, StandardCharsets.UTF_8));
+
+            String decodedJobId = CommonUtil.decodeJobId(encodedJobId);
+            assertNotNull(decodedJobId);
+            assertEquals(decodedJobId, jobId);
+        }
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testJobIdDecodingInvalid() throws Exception {
+        CommonUtil.decodeJobId("bogus");
+    }
+}
\ No newline at end of file
diff --git a/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtilTest.java b/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtilTest.java
index a223ba5f9ed..b746e62e483 100644
--- a/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtilTest.java
+++ b/operation/fhir-operation-bulkdata/src/test/java/org/linuxforhealth/fhir/operation/bulkdata/util/BulkDataExportUtilTest.java
@@ -26,11 +26,6 @@
 
 import javax.ws.rs.core.MediaType;
 
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
 import org.linuxforhealth.fhir.config.FHIRConfiguration;
 import org.linuxforhealth.fhir.config.FHIRRequestContext;
 import org.linuxforhealth.fhir.core.FHIRVersionParam;
@@ -50,6 +45,10 @@
 import org.linuxforhealth.fhir.operation.bulkdata.model.PollingLocationResponse;
 import org.linuxforhealth.fhir.server.spi.operation.FHIROperationContext;
 import org.linuxforhealth.fhir.server.spi.operation.FHIROperationContext.Type;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
 
 /**
  * Test Export util
@@ -504,15 +503,14 @@ public void testCheckAndValidateJobInvalidSlash() throws FHIROperationException
 
     @Test
     public void testCheckAndValidateJobValid() throws FHIROperationException {
-        List<Parameter> parameters = List.of(Parameter.builder().name(string("job")).value(string("1234q346")).build());
-        Parameters.Builder builder = Parameters.builder();
-        builder.id(UUID.randomUUID().toString());
-        builder.parameter(parameters);
-        Parameters ps = builder.build();
+        String encodedJobId = CommonUtil.encodeJobId(555L);
+        Parameters ps = Parameters.builder()
+                .parameter(Parameter.builder().name("job").value(encodedJobId).build())
+                .build();
 
         String result = util.checkAndValidateJob(ps);
         assertNotNull(result);
-        assertEquals(result, "1234q346");
+        assertEquals(result, "555");
     }
 
     @Test
diff --git a/operation/fhir-operation-bulkdata/src/test/resources/config/config/fhir-server-config.json b/operation/fhir-operation-bulkdata/src/test/resources/config/config/fhir-server-config.json
index 4930e26e25b..c2d90dd4f8b 100644
--- a/operation/fhir-operation-bulkdata/src/test/resources/config/config/fhir-server-config.json
+++ b/operation/fhir-operation-bulkdata/src/test/resources/config/config/fhir-server-config.json
@@ -49,7 +49,7 @@
                 },
                 "pageSize": 100,
                 "_comment": "max of 1000",
-                "batchIdEncryptionKey": "change-password",
+                "batchIdEncodingKey": "change-password",
                 "maxPartitions": 3,
                 "maxInputs": 5,
                 "systemExportImpl": "none"
diff --git a/operation/fhir-operation-bulkdata/src/test/resources/config/default/fhir-server-config.json b/operation/fhir-operation-bulkdata/src/test/resources/config/default/fhir-server-config.json
index 4927754695c..99fba683e38 100644
--- a/operation/fhir-operation-bulkdata/src/test/resources/config/default/fhir-server-config.json
+++ b/operation/fhir-operation-bulkdata/src/test/resources/config/default/fhir-server-config.json
@@ -21,7 +21,7 @@
                 },
                 "pageSize": 100,
                 "_comment": "max of 1000",
-                "batchIdEncryptionKey": "change-password",
+                "batchIdEncodingKey": "change-password",
                 "maxPartitions": 3,
                 "maxInputs": 5,
                 "systemExportImpl": "none"
diff --git a/operation/fhir-operation-bulkdata/src/test/resources/config/not-config/fhir-server-config.json b/operation/fhir-operation-bulkdata/src/test/resources/config/not-config/fhir-server-config.json
index 4930e26e25b..c2d90dd4f8b 100644
--- a/operation/fhir-operation-bulkdata/src/test/resources/config/not-config/fhir-server-config.json
+++ b/operation/fhir-operation-bulkdata/src/test/resources/config/not-config/fhir-server-config.json
@@ -49,7 +49,7 @@
                 },
                 "pageSize": 100,
                 "_comment": "max of 1000",
-                "batchIdEncryptionKey": "change-password",
+                "batchIdEncodingKey": "change-password",
                 "maxPartitions": 3,
                 "maxInputs": 5,
                 "systemExportImpl": "none"
diff --git a/operation/fhir-operation-bulkdata/src/test/resources/config/provider/fhir-server-config.json b/operation/fhir-operation-bulkdata/src/test/resources/config/provider/fhir-server-config.json
index a74d3df863d..2365a31d165 100644
--- a/operation/fhir-operation-bulkdata/src/test/resources/config/provider/fhir-server-config.json
+++ b/operation/fhir-operation-bulkdata/src/test/resources/config/provider/fhir-server-config.json
@@ -25,7 +25,7 @@
 					"resourceCountThreshold": 200000
 				},
 				"pageSize": 100,
-				"batchIdEncryptionKey": "change-password",
+				"batchIdEncodingKey": "change-password",
 				"maxPartitions": 3,
 				"maxInputs": 5,
 				"maxChunkReadTime": "90000",
