diff --git a/client/README.md b/client/README.md
index 2b9ebc8ef7ba0f2843efb8965880036cea1080ff..b243904dc304e154d51209ee1cf0ca13e96df049 100644
--- a/client/README.md
+++ b/client/README.md
@@ -1,2 +1,27 @@
 ## Client Module
 
+### API Flow
+The SdkClientFactory provides fluent API client both for **Sender** and **Subscriber**.
+
+As the flow chart belwo shows, the fluent client ntercae guide you through all essentials calls
+in order to hand in a **Submission**.
+
+#### Api client flow for sending a submission
+
+```mermaid
+flowchart LR
+
+A[retrieveOAuthToken] --> B(Upload)
+B -->|uploadAttachment| C[Result 1]
+B -->|uploadData| D[Result 2]
+```
+
+#### Api client flow for subscribing to a submission
+
+```mermaid
+flowchart TD
+
+A[retrieveOAuthToken] --> B(Upload)
+B -->|uploadAttachment| C[Result 1]
+B -->|uploadData| D[Result 2]
+```
\ No newline at end of file
diff --git a/client/src/main/java/de/fitko/fitconnect/TestRunner.java b/client/src/main/java/de/fitko/fitconnect/TestRunner.java
index 830e20dddc41a1aa93249be6647ef1d903ff45e1..5af8022423fb65c301aea5bb3c9a2081a30dbdfd 100644
--- a/client/src/main/java/de/fitko/fitconnect/TestRunner.java
+++ b/client/src/main/java/de/fitko/fitconnect/TestRunner.java
@@ -3,27 +3,25 @@ package de.fitko.fitconnect;
 import de.fitko.fitconnect.api.domain.model.metadata.Metadata;
 import de.fitko.fitconnect.api.domain.model.metadata.data.Data;
 import de.fitko.fitconnect.api.domain.model.submission.Submission;
-import de.fitko.fitconnect.client.SdkClientFactory;
 import de.fitko.fitconnect.client.SenderClient;
-
-import java.util.Collections;
+import de.fitko.fitconnect.client.SubscriberClient;
 
 public class TestRunner {
 
     public static void main(String[] args) {
 
-        final SenderClient senderClient = SdkClientFactory.senderClient();
-
         var clientId = "781f6213-0f0f-4a79-9372-e7187ffda98b";
         var secret = "PnzR8Vbmhpv_VwTkT34wponqXWK8WBm-LADlryYdV4o";
 
-        // sample high -level- api calls to send a submission
-        senderClient.authenticate(clientId,secret)
-                .printToken()
+        final Submission sentSubmission = SenderClient.builder()
+                .authenticate(clientId, secret)
                 .createSubmission(Submission.builder().build())
-                .uploadAttachments(Collections.emptyList())
+                .uploadAttachments()
                 .sendSubmission(Metadata.builder().build(), Data.builder().build());
 
+        SubscriberClient.builder()
+                .authenticate(clientId, secret);
+
     }
 
 }
diff --git a/client/src/main/java/de/fitko/fitconnect/client/SdkClientFactory.java b/client/src/main/java/de/fitko/fitconnect/client/SdkClientFactory.java
deleted file mode 100644
index 38477a79209ccf05e6701093ed588868109f3c25..0000000000000000000000000000000000000000
--- a/client/src/main/java/de/fitko/fitconnect/client/SdkClientFactory.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.fitko.fitconnect.client;
-
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import de.fitko.fitconnect.dependency.SdkModule;
-import de.fitko.fitconnect.api.services.Sender;
-import de.fitko.fitconnect.api.services.Subscriber;
-import org.springframework.web.client.RestTemplate;
-
-public class SdkClientFactory {
-
-    private static final Injector injector = Guice.createInjector(new SdkModule());
-
-    public static SenderClient senderClient() {
-        var sender = injector.getInstance(Sender.class);
-        var restTemplate = injector.getProvider(RestTemplate.class).get();
-        return new SenderClient(sender, restTemplate);
-    }
-
-    public static SubscriberClient subscriberClient(){
-        return new SubscriberClient(injector.getInstance(Subscriber.class));
-    }
-}
diff --git a/client/src/main/java/de/fitko/fitconnect/client/SenderClient.java b/client/src/main/java/de/fitko/fitconnect/client/SenderClient.java
index 4306fdd8ef09804378d05eedb9b87d41d1e687c3..bf67f27732fc22fa1fc0f104577eb969363d5c01 100644
--- a/client/src/main/java/de/fitko/fitconnect/client/SenderClient.java
+++ b/client/src/main/java/de/fitko/fitconnect/client/SenderClient.java
@@ -1,68 +1,97 @@
 package de.fitko.fitconnect.client;
 
-import com.google.inject.Inject;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
 import de.fitko.fitconnect.api.domain.auth.OAuthToken;
 import de.fitko.fitconnect.api.domain.model.metadata.Metadata;
-import de.fitko.fitconnect.api.domain.model.metadata.attachment.Attachment;
 import de.fitko.fitconnect.api.domain.model.metadata.data.Data;
 import de.fitko.fitconnect.api.domain.model.submission.Submission;
 import de.fitko.fitconnect.api.services.Sender;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.client.RestTemplate;
+import de.fitko.fitconnect.api.services.metadata.MetadataService;
+import de.fitko.fitconnect.dependency.SdkModule;
 
-import java.util.List;
 import java.util.Optional;
 
+/**
+ * A fluent client for handing in a {@link Submission}
+ */
 public class SenderClient {
 
-    private static final Logger logger = LoggerFactory.getLogger(SenderClient.class);
+    private static final Injector injector = Guice.createInjector(new SdkModule());
 
-    private final Sender sender;
-    private Optional<OAuthToken> token = Optional.empty();
+    private SenderClient() {}
 
-    @Inject
-    public SenderClient(final Sender sender, RestTemplate restTemplate){
-        this.sender = sender;
-    }
-    
-    public SenderClient authenticate(String clientId, String secret, String...scope){
-        this.token = sender.retrieveOAuthToken(clientId,secret,scope);
-        return this;
+     public static Authenticate builder() {
+         Sender sender = injector.getInstance(Sender.class);
+         MetadataService metadataService = injector.getInstance(MetadataService.class);
+         return new ClientBuilder(sender, metadataService);
     }
 
-    public SenderClient createSubmission(final Submission submission){
-        checkIfAuthenticated();
-        // TODO implement sendSubmission
-        logger.info("created new submission");
-        return this;
+    public interface Authenticate {
+        /**
+         *
+         * @param clientId
+         * @param secret
+         * @param scope
+         * @return
+         */
+        CreateSubmission authenticate(String clientId, String secret, String... scope);
     }
 
-    public Submission sendSubmission(final Metadata metadata, final Data data){
-        checkIfAuthenticated();
-        // TODO implement
-        logger.info("successfully sent submission");
-        return Submission.builder().build();
+    public interface AttachmentUpload {
+        SendSubmission uploadAttachments();
     }
 
-    public SenderClient uploadAttachments(final List<Attachment> attachments){
-        checkIfAuthenticated();
-        // TODO implement
-        logger.info("uploaded " + attachments.size() + " attachments");
-        return this;
+    public interface CreateSubmission {
+        AttachmentUpload createSubmission(Submission submission);
     }
 
-    public SenderClient printToken(){
-        checkIfAuthenticated();
-        logger.info("retrieved access token: " + this.token.get().getAccessToken());
-        return this;
+    public interface SendSubmission {
+        Submission sendSubmission(Metadata metaData, Data data);
     }
 
-    private void checkIfAuthenticated() {
-        if(token.isEmpty()){
-            throw new IllegalStateException("not authenticated, please authenticate first");
+    public static class ClientBuilder implements Authenticate, AttachmentUpload, CreateSubmission, SendSubmission {
+
+        private final MetadataService metadataService;
+        private Sender sender;
+        private Submission submission;
+        private Optional<OAuthToken> token;
+
+        private ClientBuilder(Sender sender, MetadataService metadataService) {
+            this.sender = sender;
+            this.metadataService = metadataService;
+        }
+
+        @Override
+        public CreateSubmission authenticate(String clientId, String secret, String... scope) {
+            this.token = sender.retrieveOAuthToken(clientId, secret, scope);
+            return this;
+        }
+
+        @Override
+        public SendSubmission uploadAttachments() {
+            checkIfAuthenticated();
+            //metadataService.createMetadata();
+            return this;
+        }
+
+        @Override
+        public AttachmentUpload createSubmission(Submission submission) {
+            checkIfAuthenticated();
+            sender.sendSubmission(submission);
+            return this;
         }
-        // TODO check if token is still valid
-    }
 
-}
+        @Override
+        public Submission sendSubmission(Metadata metaData, Data data) {
+            checkIfAuthenticated();
+            return sender.sendSubmission(Submission.builder().build());
+        }
+
+        private void checkIfAuthenticated(){
+            if(this.token == null || this.token.isEmpty()){
+                throw new IllegalStateException("Not authenticated, please authenticate first");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/client/src/main/java/de/fitko/fitconnect/client/SubscriberClient.java b/client/src/main/java/de/fitko/fitconnect/client/SubscriberClient.java
index ea4f79d4ebe3fd904fb1c3a3f5cb3632cdd5dae5..77f3c997371bc2fd92bc8e5977d54c6e5562e1c4 100644
--- a/client/src/main/java/de/fitko/fitconnect/client/SubscriberClient.java
+++ b/client/src/main/java/de/fitko/fitconnect/client/SubscriberClient.java
@@ -1,12 +1,67 @@
 package de.fitko.fitconnect.client;
 
-import com.google.inject.Inject;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import de.fitko.fitconnect.api.domain.auth.OAuthToken;
 import de.fitko.fitconnect.api.services.Subscriber;
+import de.fitko.fitconnect.dependency.SdkModule;
 
+import java.util.Optional;
+
+/**
+ * A fluent client for handing in a subscription for a {@link Subscriber}
+ */
 public class SubscriberClient {
 
-    @Inject
-    public SubscriberClient(final Subscriber subscriber){
+    private static final Injector injector = Guice.createInjector(new SdkModule());
+
+    private SubscriberClient() {}
+
+     public static Authenticate builder() {
+         Subscriber subscriber = injector.getInstance(Subscriber.class);
+         return new ClientBuilder(subscriber);
+    }
+
+    public interface Authenticate {
+        /**
+         *
+         * @param clientId
+         * @param secret
+         * @param scope
+         * @return
+         */
+        AttachmentUpload authenticate(String clientId, String secret, String... scope);
+    }
+
+    public interface AttachmentUpload {
+        void uploadAttachments();
     }
 
-}
+    public static class ClientBuilder implements Authenticate, AttachmentUpload{
+
+        private Subscriber subscriber;
+        private Optional<OAuthToken> token;
+
+        private ClientBuilder(Subscriber subscriber) {
+            this.subscriber = subscriber;
+        }
+
+        @Override
+        public AttachmentUpload authenticate(String clientId, String secret, String... scope) {
+            this.token = subscriber.retrieveOAuthToken(clientId, secret, scope);
+            return this;
+        }
+
+        @Override
+        public void uploadAttachments() {
+            checkIfAuthenticated();
+            //metadataService.createMetadata();
+        }
+
+        private void checkIfAuthenticated(){
+            if(this.token == null || this.token.isEmpty()){
+                throw new IllegalStateException("Not authenticated, please authenticate first");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/client/src/main/java/de/fitko/fitconnect/cmd/CommandLineRunner.java b/client/src/main/java/de/fitko/fitconnect/cmd/CommandLineRunner.java
index 43c473542505c289e0cd8ff73fa80634b347936b..9145ff801a6a9179437d57fb4e06bf097559370b 100644
--- a/client/src/main/java/de/fitko/fitconnect/cmd/CommandLineRunner.java
+++ b/client/src/main/java/de/fitko/fitconnect/cmd/CommandLineRunner.java
@@ -1,7 +1,6 @@
 package de.fitko.fitconnect.cmd;
 
 import com.beust.jcommander.JCommander;
-import de.fitko.fitconnect.client.SdkClientFactory;
 import de.fitko.fitconnect.client.SenderClient;
 
 public class CommandLineRunner {
@@ -15,16 +14,12 @@ public class CommandLineRunner {
 
         build.parse(args);
 
-        final SenderClient senderClient = SdkClientFactory.senderClient();
-
         var clientId = cmdArgs.clientId;
         var secret = cmdArgs.secret;
 
         // sample high -level- api calls to send a submission
-        senderClient
-                .authenticate(clientId,secret)
-                .printToken();
-
+        SenderClient.builder()
+                .authenticate(clientId, secret);
 
     }
 }