diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/CLI.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/CLI.java
index b89885844020b1314a8a55b64c107de5c19fafbc..51527dbfe75a76d0819de8f3bacb11111c5200a4 100644
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/CLI.java
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/CLI.java
@@ -1,5 +1,9 @@
 package dev.fitko.fitconnect.cli;
 
+import dev.fitko.fitconnect.cli.commands.GetAllSubmissionsCommand;
+import dev.fitko.fitconnect.cli.commands.GetSubmissionCommand;
+import dev.fitko.fitconnect.cli.commands.KeyGenCommand;
+import dev.fitko.fitconnect.cli.commands.ListCommand;
 import org.fusesource.jansi.AnsiConsole;
 import picocli.CommandLine;
 
@@ -12,7 +16,11 @@ import static java.lang.System.exit;
 import static java.lang.System.out;
 
 @CommandLine.Command(version = "2.0.0",
-        subcommands = {KeyGenCommand.class, ListCommand.class},
+        subcommands = {
+                KeyGenCommand.class,
+                ListCommand.class,
+                GetSubmissionCommand.class,
+                GetAllSubmissionsCommand.class},
         mixinStandardHelpOptions = true)
 public class CLI implements Runnable {
     private static final String LOGO = "/splash_screen_banner.txt";
@@ -24,6 +32,7 @@ public class CLI implements Runnable {
         int exitCode = commandLine.execute(args);
         exit(exitCode);
     }
+
     @Override
     public void run() {
         final CommandLine.Help.Ansi ansi = new CommandLine.Help.ColorScheme.Builder().ansi();
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/ConfigCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ConfigCommand.java
similarity index 93%
rename from java/cli/src/main/java/dev/fitko/fitconnect/cli/ConfigCommand.java
rename to java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ConfigCommand.java
index 0b0bbd1faac844119b015c164785e1f795c3714e..920a7987b7fe56d5d627a84e1c9786a32958ac2a 100644
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/ConfigCommand.java
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ConfigCommand.java
@@ -1,4 +1,4 @@
-package dev.fitko.fitconnect.cli;
+package dev.fitko.fitconnect.cli.commands;
 
 import dev.fitko.fitconnect.api.config.ApplicationConfig;
 import dev.fitko.fitconnect.client.bootstrap.ApplicationConfigLoader;
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/CreateTestKeysCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/CreateTestKeysCommand.java
deleted file mode 100644
index 4901e7e49d619e475801f389febfc73366710651..0000000000000000000000000000000000000000
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/CreateTestKeysCommand.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package dev.fitko.fitconnect.cli.commands;
-
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
-
-@Parameters(
-        commandNames = {CreateTestKeysCommand.CREATE_TEST_KEYS_COMMAND_NAME},
-        commandDescription = "Generates JWK test keys for encryption, decryption, signing and signature validation",
-        separators = "="
-)
-public class CreateTestKeysCommand {
-
-    public static final String CREATE_TEST_KEYS_COMMAND_NAME = "keygen";
-
-    @Parameter(names = {"--outDir"}, description = "Output directory folder where the generated test keys are written to", arity = 1)
-    public String outputDir;
-
-    @Parameter(names = {"--withConfig"}, description = "Generates config.yaml with paths of the generated keys", arity = 1)
-    public boolean generateConfig;
-}
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetAllSubmissionsCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetAllSubmissionsCommand.java
index 9ad74e0e6fad6e344e540b41578c03fda8f620be..551105c5e10b31f7723afe04920082ad6d344f31 100644
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetAllSubmissionsCommand.java
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetAllSubmissionsCommand.java
@@ -1,27 +1,44 @@
 package dev.fitko.fitconnect.cli.commands;
 
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
-import dev.fitko.fitconnect.cli.util.UUIDConverter;
-import dev.fitko.fitconnect.cli.util.UUIDValidator;
+import dev.fitko.fitconnect.api.config.ApplicationConfig;
+import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
+import dev.fitko.fitconnect.client.SubscriberClient;
+import dev.fitko.fitconnect.client.bootstrap.ApplicationConfigLoader;
+import dev.fitko.fitconnect.client.bootstrap.ClientFactory;
+import lombok.SneakyThrows;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
 
+import java.nio.file.Path;
+import java.util.Set;
 import java.util.UUID;
 
-@Parameters(
-        commandNames = {GetAllSubmissionsCommand.GET_ALL_CMD_NAME},
-        commandDescription = "Fetches all available submission for a destination",
-        separators = "="
-)
-public class GetAllSubmissionsCommand {
+@CommandLine.Command(name = "get", description = "Fetch a submission by id", mixinStandardHelpOptions = true)
+public class GetAllSubmissionsCommand implements Runnable {
 
-    public static final String GET_ALL_CMD_NAME = "all";
+    private static final Logger LOGGER = LoggerFactory.getLogger(GetAllSubmissionsCommand.class);
 
-    @Parameter(names = { "--config" }, description = "Path to the config yaml", arity = 1)
-    public String config;
+    @CommandLine.Option(names = {"--config"}, description = "Path to the config yaml", required = true)
+    public Path configPath;
 
-    @Parameter(names = { "--destinationId" }, description = "Unique destination identifier in UUID format", converter = UUIDConverter.class, validateWith = UUIDValidator.class, arity = 1, required = true)
-    public UUID destinationId;
+    @CommandLine.Option(names = {"-d", "--dest"}, required = true, description = "UUID of the destination")
+    private UUID destinationId;
 
-    @Parameter(names = { "--target" }, description = "Target folder where attachments and data is written to", arity = 1)
-    public String targetFolder;
+    @CommandLine.Option(names = {"--target"}, description = "Target folder where attachments and data is written to", required = false)
+    public Path targetFolder;
+
+    @Override
+    @SneakyThrows
+    public void run() {
+
+        LOGGER.info("Getting all available submissions for destination {}", destinationId);
+
+        final ApplicationConfig config = ApplicationConfigLoader.loadConfigFromPath(configPath);
+        final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
+
+        final GetSubmissionCommand getSubmissionCommand = new GetSubmissionCommand();
+        final Set<SubmissionForPickup> submissions = subscriberClient.getAvailableSubmissionsForDestination(destinationId);
+        submissions.forEach(submission -> getSubmissionCommand.getSubmission(subscriberClient, submission.getSubmissionId(), targetFolder));
+    }
 }
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetOneSubmissionCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetOneSubmissionCommand.java
deleted file mode 100644
index fd74bd7f7d4cbf063424edd4f5c0d327357487e5..0000000000000000000000000000000000000000
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetOneSubmissionCommand.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package dev.fitko.fitconnect.cli.commands;
-
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
-import dev.fitko.fitconnect.cli.util.UUIDConverter;
-import dev.fitko.fitconnect.cli.util.UUIDValidator;
-
-import java.util.UUID;
-
-
-@Parameters(
-        commandNames = {GetOneSubmissionCommand.GET_CMD_NAME},
-        commandDescription = "Fetches one submission by id",
-        separators = "="
-)
-public class GetOneSubmissionCommand {
-
-    public static final String GET_CMD_NAME = "get";
-
-    @Parameter(names = { "--config" }, description = "Path to the config yaml", arity = 1)
-    public String config;
-
-    @Parameter(names = { "--submissionId" }, description = "Unique submission identifier in UUID format", converter = UUIDConverter.class, validateWith = UUIDValidator.class, arity = 1, required = true)
-    public UUID submissionId;
-
-    @Parameter(names = { "--target" }, description = "Target folder where attachments and data is written to", arity = 1)
-    public String targetFolder;
-}
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetSubmissionCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetSubmissionCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ada8619f463265b9a5b787f68108a27baa65347
--- /dev/null
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/GetSubmissionCommand.java
@@ -0,0 +1,60 @@
+package dev.fitko.fitconnect.cli.commands;
+
+import dev.fitko.fitconnect.api.config.ApplicationConfig;
+import dev.fitko.fitconnect.cli.util.SubmissionWriter;
+import dev.fitko.fitconnect.client.SubscriberClient;
+import dev.fitko.fitconnect.client.bootstrap.ApplicationConfigLoader;
+import dev.fitko.fitconnect.client.bootstrap.ClientFactory;
+import dev.fitko.fitconnect.core.utils.StopWatch;
+import lombok.SneakyThrows;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+
+import java.nio.file.Path;
+import java.util.UUID;
+
+@CommandLine.Command(name = "get", description = "Fetch a submission by id", mixinStandardHelpOptions = true)
+public class GetSubmissionCommand implements Runnable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(GetSubmissionCommand.class);
+
+    @CommandLine.Option(names = {"-c", "--config"}, required = true, description = "Path to the config yaml with subscriber clientId and clientSecret")
+    public Path configPath;
+
+    @CommandLine.Option(names = {"-id", "--submissionId"}, description = "Unique submission identifier in UUID format", required = true)
+    public UUID submissionId;
+
+    @CommandLine.Option(names = {"--target"}, description = "Target folder where attachments and data is written to", required = false)
+    public Path targetFolder;
+
+    @Override
+    public void run() {
+
+        LOGGER.info("Getting submission for id {}", submissionId);
+
+        final ApplicationConfig config = ApplicationConfigLoader.loadConfigFromPath(configPath);
+        final SubscriberClient subscriberClient = ClientFactory.createSubscriberClient(config);
+
+        getSubmission(subscriberClient, submissionId, targetFolder);
+    }
+
+    @SneakyThrows
+    public void getSubmission(SubscriberClient subscriberClient, UUID submissionId, Path targetFolder) {
+        LOGGER.info("Getting submission for id {}", submissionId);
+
+        final var startTime = StopWatch.start();
+        final var submission = subscriberClient.requestSubmission(submissionId);
+        LOGGER.info("Submission download took {}", StopWatch.stop(startTime));
+        if (submission == null) {
+            LOGGER.info("No submission found for submission id {}", submissionId);
+        } else {
+            submission.acceptSubmission();
+            SubmissionWriter.writeSubmissionData(submission, getTargetFolderPath(targetFolder, submissionId));
+        }
+    }
+
+    private String getTargetFolderPath(Path targetFolder, UUID submissionId) {
+        return targetFolder != null ? targetFolder + "/" + submissionId : submissionId.toString();
+    }
+}
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/KeyGenCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/KeyGenCommand.java
similarity index 90%
rename from java/cli/src/main/java/dev/fitko/fitconnect/cli/KeyGenCommand.java
rename to java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/KeyGenCommand.java
index ecd9fce65e5392c5058bc2f81301a5629d1be727..77bb043b8fcbda264da5bf39547c668e8f4ef2fd 100644
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/KeyGenCommand.java
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/KeyGenCommand.java
@@ -1,4 +1,4 @@
-package dev.fitko.fitconnect.cli;
+package dev.fitko.fitconnect.cli.commands;
 
 import dev.fitko.fitconnect.api.domain.crypto.JWKPair;
 import dev.fitko.fitconnect.tools.keygen.KeyWriter;
@@ -10,12 +10,11 @@ import picocli.CommandLine;
 import picocli.CommandLine.Option;
 
 import java.nio.file.Path;
-import java.util.concurrent.Callable;
 
 import static dev.fitko.fitconnect.tools.keygen.TestKeyBuilder.DEFAULT_KEY_SIZE;
 
 @CommandLine.Command(name = "keygen", description = "Generate JWKs for TEST usage", mixinStandardHelpOptions = true)
-public class KeyGenCommand implements Callable<Integer> {
+public class KeyGenCommand implements Runnable {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(KeyGenCommand.class);
 
@@ -26,8 +25,7 @@ public class KeyGenCommand implements Callable<Integer> {
     private boolean generateConfig;
 
     @Override
-    public Integer call() {
-
+    public void run() {
         LOGGER.info("Generating Test JWKs ...");
 
         final JWKPair encryptionKeyPair = TestKeyBuilder.generateEncryptionKeyPair(DEFAULT_KEY_SIZE);
@@ -43,6 +41,5 @@ public class KeyGenCommand implements Callable<Integer> {
         }
 
         KeyWriter.writeKeys(settingsBuilder.build());
-        return null;
     }
 }
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ListAllSubmissionsCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ListAllSubmissionsCommand.java
deleted file mode 100644
index 00994674ac2d8951348b574250a501899ae1d680..0000000000000000000000000000000000000000
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ListAllSubmissionsCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package dev.fitko.fitconnect.cli.commands;
-
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
-import dev.fitko.fitconnect.cli.util.UUIDConverter;
-import dev.fitko.fitconnect.cli.util.UUIDValidator;
-
-import java.util.UUID;
-
-@Parameters(
-        commandNames = {ListAllSubmissionsCommand.LIST_CMD_NAME},
-        commandDescription = "Lists available submissions",
-        separators = "="
-)
-public class ListAllSubmissionsCommand {
-
-    public static final String LIST_CMD_NAME = "list";
-
-    @Parameter(names = { "--config" }, description = "Path to the config yaml", arity = 1)
-    public String config;
-
-    @Parameter(names = { "--destinationId" }, description = "Unique destination identifier in UUID format", converter = UUIDConverter.class,  validateWith = UUIDValidator.class, arity = 1, required = true)
-    public UUID destinationId;
-}
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/ListCommand.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ListCommand.java
similarity index 94%
rename from java/cli/src/main/java/dev/fitko/fitconnect/cli/ListCommand.java
rename to java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ListCommand.java
index 51e5942e4570d0587b9db0376ba46238f1d40685..001352246a11e178351992af59614b7e8060c4c8 100644
--- a/java/cli/src/main/java/dev/fitko/fitconnect/cli/ListCommand.java
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/commands/ListCommand.java
@@ -1,4 +1,4 @@
-package dev.fitko.fitconnect.cli;
+package dev.fitko.fitconnect.cli.commands;
 
 import dev.fitko.fitconnect.api.config.ApplicationConfig;
 import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
@@ -21,7 +21,7 @@ public class ListCommand implements Runnable {
     @CommandLine.Option(names = {"-c", "--config"}, required = true, description = "Path to the config yaml with subscriber clientId and clientSecret")
     private Path configPath;
 
-    @CommandLine.Option(names = {"-d", "--dest"}, required = true, description = "UUID of the destinationId to poll")
+    @CommandLine.Option(names = {"-d", "--dest"}, required = true, description = "UUID of the destination to poll")
     private UUID destinationId;
 
     @Override
diff --git a/java/cli/src/main/java/dev/fitko/fitconnect/cli/util/SubmissionWriter.java b/java/cli/src/main/java/dev/fitko/fitconnect/cli/util/SubmissionWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e3a44601ad325bd2e57b22cd36dfc1c9c472cdf
--- /dev/null
+++ b/java/cli/src/main/java/dev/fitko/fitconnect/cli/util/SubmissionWriter.java
@@ -0,0 +1,66 @@
+package dev.fitko.fitconnect.cli.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import dev.fitko.fitconnect.api.domain.model.attachment.Attachment;
+import dev.fitko.fitconnect.api.domain.model.metadata.Metadata;
+import dev.fitko.fitconnect.api.domain.subscriber.ReceivedSubmission;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class SubmissionWriter {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SubmissionWriter.class);
+
+    private static final ObjectWriter JSON_WRITER = new ObjectMapper().writerWithDefaultPrettyPrinter();
+
+    public static void writeSubmissionData(final ReceivedSubmission receivedSubmission, final String dataDirPath) throws IOException {
+
+        LOGGER.info("Creating data directory for submission in {}", dataDirPath);
+        Files.createDirectories(Path.of(dataDirPath));
+
+        final var fileEnding = AttachmentDataType.getFileTypeFromMimeType(receivedSubmission.getDataMimeType());
+        final var filePath = Path.of(dataDirPath + "/data." + fileEnding);
+        LOGGER.info("Writing data.{}", fileEnding);
+        Files.write(filePath, receivedSubmission.getDataAsString().getBytes(StandardCharsets.UTF_8));
+
+        LOGGER.info("Writing metadata.json");
+        final Metadata metadata = receivedSubmission.getMetadata();
+        Files.write(Path.of(dataDirPath, "metadata.json"), JSON_WRITER.writeValueAsString(metadata).getBytes());
+
+        final List<Attachment> attachments = receivedSubmission.getAttachments();
+        for (int i = 0; i < attachments.size(); i++) {
+            final Attachment attachment = attachments.get(i);
+            final String filename = getAttachmentFilename(attachment, i);
+            LOGGER.info("Writing attachment {}", filename);
+            final Path tragetPath = Path.of(dataDirPath, filename);
+            if (attachment.isInMemoryAttachment()) {
+                Files.write(tragetPath, attachment.getDataAsBytes());
+            } else {
+                try (OutputStream os = Files.newOutputStream(tragetPath)) {
+                    attachment.getDataAsInputStream().transferTo(os);
+                }
+            }
+        }
+    }
+
+    private static String getAttachmentFilename(Attachment attachment, int i) {
+        if (attachment.getFileName() == null) {
+            if (attachment.getMimeType() != null) {
+                return "attachment_" + i + "." + attachment.getMimeType().split("/")[1];
+            }
+            return attachment + "_" + i;
+        }
+        return attachment.getFileName();
+    }
+}