diff --git a/banking-client/src/main/java/ufrn/imd/utils/MachineState.java b/banking-client/src/main/java/ufrn/imd/utils/MachineState.java
index 975d268b2ebda092b909bd8c0bf19ef69a5bb142..4f1834f4fe00066168878d3ae62f93f2c7b19f2e 100644
--- a/banking-client/src/main/java/ufrn/imd/utils/MachineState.java
+++ b/banking-client/src/main/java/ufrn/imd/utils/MachineState.java
@@ -5,6 +5,7 @@ import ufrn.imd.controller.Controller;
 import ufrn.imd.domain.Account;
 import ufrn.imd.domain.Client;
 import ufrn.imd.utils.message.DepositMessage;
+import ufrn.imd.utils.message.TransferMessage;
 import ufrn.imd.utils.message.WithdrawalMessage;
 
 import java.net.MalformedURLException;
@@ -13,9 +14,7 @@ import java.rmi.NotBoundException;
 import java.rmi.RemoteException;
 import java.util.Scanner;
 
-import static ufrn.imd.utils.NameSpace.HOST_BALANCE_SERVICE;
-import static ufrn.imd.utils.NameSpace.HOST_DEPOSIT_SERVICE;
-import static ufrn.imd.utils.NameSpace.HOST_WITHDRAWAL_SERVICE;
+import static ufrn.imd.utils.NameSpace.*;
 
 @Data
 public class MachineState {
@@ -25,6 +24,7 @@ public class MachineState {
     public static final String DEPOSIT = "DEPOSIT";
     public static final String BALANCE = "BALANCE";
     public static final String WITHDRAWAL = "WITHDRAWAL";
+    public static final String TRANSFER = "TRANSFER";
 
     public static final String START = "START";
     public static final String INVALID_INPUT = "INVALID_INPUT";
@@ -59,6 +59,8 @@ public class MachineState {
             state = START;
         } else if(state.equals(WITHDRAWAL)) {
             state = START;
+        } else if(state.equals(TRANSFER)) {
+            state = START;
         }
     }
 
@@ -69,7 +71,8 @@ public class MachineState {
                     !inputValue.equals(QUIT) &&
                     !inputValue.equals(DEPOSIT) &&
                     !inputValue.equals(BALANCE) &&
-                    !inputValue.equals(WITHDRAWAL)) {
+                    !inputValue.equals(WITHDRAWAL) &&
+                    !inputValue.equals(TRANSFER)) {
                 inputValue = INVALID_INPUT;
             }
         } else if(state.equals(DEPOSIT)) {
@@ -124,6 +127,30 @@ public class MachineState {
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
+        } else if(state.equals(TRANSFER)) {
+            String accountNumber = sc.nextLine();
+            System.out.println(">>> Please enter with the value that you want transfer");
+            String v = sc.nextLine();
+
+            Client client = new Client(1);
+            Account account = new Account(null, accountNumber, null);
+            TransferMessage transferMessage = new TransferMessage(client, account, Double.parseDouble(v));
+            Controller server = (Controller) Naming.lookup(HOST_TRANSFER_SERVICE);
+            ServerResponse response = server.getResponse(transferMessage);
+            if(response.getStatus() == 200) {
+                System.out.println(
+                        String.format(">>> Your balance is: %.2f", ((Account)response.getBody()).getBalance())
+                );
+            } else if(response.getStatus() == 500) {
+                System.out.println(
+                        String.format(">>> %s", response.getMessage())
+                );
+            }
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
         }
     }
 
@@ -135,9 +162,9 @@ public class MachineState {
             } else if(state.equals(START)) {
                 System.out.println("These are the avaliable operations");
                 System.out.println("---------------------------------");
-                System.out.println(" - deposit \t - balance");
-                System.out.println(" - withdrawal \t - quit");
-
+                System.out.println(" - deposit \t\t - balance");
+                System.out.println(" - withdrawal \t - transfer");
+                System.out.println(" - quit");
                 System.out.println("---------------------------------");
                 Thread.sleep(1000);
             } else if(state.equals(READ)) {
@@ -151,6 +178,9 @@ public class MachineState {
             } else if(state.equals(WITHDRAWAL)) {
                 System.out.println(">>> Starting withdrawal operation");
                 System.out.println(">>> Please enter the value you want to withdraw");
+            } else if(state.equals(TRANSFER)) {
+                System.out.println(">>> Starting transfer operation");
+                System.out.println(">>> Please enter with the recipient's account number");
             }
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
diff --git a/banking-client/src/main/java/ufrn/imd/utils/NameSpace.java b/banking-client/src/main/java/ufrn/imd/utils/NameSpace.java
index 68378ddd071645b9312f191151677cb136ac9273..3cc1c46f5f9d8cced8686b7065fcf43128a4d6c2 100644
--- a/banking-client/src/main/java/ufrn/imd/utils/NameSpace.java
+++ b/banking-client/src/main/java/ufrn/imd/utils/NameSpace.java
@@ -4,7 +4,9 @@ public class NameSpace {
     public final static Integer PORT_WITHDRAWAL_SERVICE = 1906;
     public static final Integer PORT_DEPOSIT_SERVICE = 1907;
     public static final Integer PORT_BALANCE_SERVICE = 1908;
+    public static final Integer PORT_TRANSFER_SERVICE = 1909;
     public final static String HOST_WITHDRAWAL_SERVICE = String.format("rmi://127.0.0.1:%d/%s", PORT_WITHDRAWAL_SERVICE, "withdrawal");
     public static final String HOST_DEPOSIT_SERVICE = String.format("rmi://127.0.0.1:%d/%s", PORT_DEPOSIT_SERVICE, "deposit");
     public static final String HOST_BALANCE_SERVICE = String.format("rmi://127.0.0.1:%d/%s", PORT_BALANCE_SERVICE, "balance");
+    public final static String HOST_TRANSFER_SERVICE = String.format("rmi://127.0.0.1:%d/%s", PORT_TRANSFER_SERVICE, "transfer");
 }
diff --git a/banking-client/src/main/java/ufrn/imd/utils/message/TransferMessage.java b/banking-client/src/main/java/ufrn/imd/utils/message/TransferMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..93fb4928759ad4746cd085a548fdcd6bbd28a4fe
--- /dev/null
+++ b/banking-client/src/main/java/ufrn/imd/utils/message/TransferMessage.java
@@ -0,0 +1,18 @@
+package ufrn.imd.utils.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import ufrn.imd.domain.Account;
+import ufrn.imd.domain.Client;
+
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+public class TransferMessage implements Serializable {
+    private static final long serialVersionUID = 2L;
+
+    private Client from;
+    private Account to;
+    private Double value;
+}
diff --git a/banking-server/src/main/java/ufrn/imd/BankingServerApp.java b/banking-server/src/main/java/ufrn/imd/BankingServerApp.java
index 4332c2c16d20ca96e4716a2b290aeb84f9bcc151..24f0ed8baec50747419f805562f02f0a63a2ac7f 100644
--- a/banking-server/src/main/java/ufrn/imd/BankingServerApp.java
+++ b/banking-server/src/main/java/ufrn/imd/BankingServerApp.java
@@ -3,10 +3,12 @@ package ufrn.imd;
 import ufrn.imd.controller.Controller;
 import ufrn.imd.controller.impl.BalanceControllerImpl;
 import ufrn.imd.controller.impl.DepositControllerImpl;
+import ufrn.imd.controller.impl.TransferControllerImpl;
 import ufrn.imd.controller.impl.WithdrawalControllerImpl;
 import ufrn.imd.repository.impl.ClientRepository;
 import ufrn.imd.service.impl.BalanceServiceImpl;
 import ufrn.imd.service.impl.DepositServiceImpl;
+import ufrn.imd.service.impl.TransferServiceImpl;
 import ufrn.imd.service.impl.WithdrawalServiceImpl;
 
 import java.net.MalformedURLException;
@@ -19,9 +21,11 @@ public class BankingServerApp {
         DepositServiceImpl depositService = new DepositServiceImpl(clientRepository);
         BalanceServiceImpl balanceService = new BalanceServiceImpl(clientRepository);
         WithdrawalServiceImpl withdrawalService = new WithdrawalServiceImpl(clientRepository);
+        TransferServiceImpl transferService = new TransferServiceImpl(clientRepository);
 
         Controller depositController = new DepositControllerImpl(depositService);
         Controller balanceController = new BalanceControllerImpl(balanceService);
         Controller withdrawalController = new WithdrawalControllerImpl(withdrawalService);
+        Controller transferController = new TransferControllerImpl(transferService);
     }
 }
diff --git a/banking-server/src/main/java/ufrn/imd/controller/impl/TransferControllerImpl.java b/banking-server/src/main/java/ufrn/imd/controller/impl/TransferControllerImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b52159ca6c2040260de3a508ff926e6c83e6cd4
--- /dev/null
+++ b/banking-server/src/main/java/ufrn/imd/controller/impl/TransferControllerImpl.java
@@ -0,0 +1,50 @@
+package ufrn.imd.controller.impl;
+
+import lombok.extern.java.Log;
+import ufrn.imd.controller.Controller;
+import ufrn.imd.service.impl.TransferServiceImpl;
+import ufrn.imd.utils.ServerResponse;
+import ufrn.imd.utils.message.TransferMessage;
+
+import java.net.MalformedURLException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Optional;
+
+import static ufrn.imd.utils.NameSpace.HOST_TRANSFER_SERVICE;
+import static ufrn.imd.utils.NameSpace.PORT_TRANSFER_SERVICE;
+
+@Log
+public class TransferControllerImpl extends UnicastRemoteObject implements Controller {
+    private final TransferServiceImpl service;
+
+    public TransferControllerImpl(TransferServiceImpl service) throws RemoteException, MalformedURLException, AlreadyBoundException {
+        super();
+        log.info("Starting Transfer service!");
+        this.service = service;
+        log.info(String.format("Initializing server in %s", HOST_TRANSFER_SERVICE));
+        LocateRegistry.createRegistry(PORT_TRANSFER_SERVICE);
+        Naming.bind(HOST_TRANSFER_SERVICE, this);
+    }
+
+    @Override
+    public ServerResponse getResponse(Object client) throws RemoteException {
+        TransferMessage transferMessage = (TransferMessage) client;
+        ServerResponse response;
+        try {
+            response = this.service.transfer(transferMessage.getValue(), Optional.of(transferMessage.getFrom()),
+                    Optional.of(transferMessage.getTo()));
+        } catch (RuntimeException e) {
+            e.printStackTrace();
+            response = ServerResponse.builder()
+                    .status(500)
+                    .message(e.getMessage())
+                    .body(transferMessage.getFrom())
+                    .build();
+        }
+        return response;
+    }
+}
diff --git a/banking-server/src/main/java/ufrn/imd/repository/impl/ClientRepository.java b/banking-server/src/main/java/ufrn/imd/repository/impl/ClientRepository.java
index 83963f78bcbb35365a86888a93c423271c0df4b3..22520da111f7fd8d9af0f94b6845501c69d1c236 100644
--- a/banking-server/src/main/java/ufrn/imd/repository/impl/ClientRepository.java
+++ b/banking-server/src/main/java/ufrn/imd/repository/impl/ClientRepository.java
@@ -22,4 +22,10 @@ public class ClientRepository implements Repository<Client> {
     public List<Client> findAll() {
         return clients;
     }
+
+    public Optional<Client> findByAccountNumber(String number) {
+        return clients.stream()
+                .filter(client -> number.equals(client.getAccount().getNumber()))
+                .findFirst();
+    }
 }
diff --git a/banking-server/src/main/java/ufrn/imd/service/impl/TransferServiceImpl.java b/banking-server/src/main/java/ufrn/imd/service/impl/TransferServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..0df30a9fc3a2b2479c57dcfb9b586bd42452e09e
--- /dev/null
+++ b/banking-server/src/main/java/ufrn/imd/service/impl/TransferServiceImpl.java
@@ -0,0 +1,48 @@
+package ufrn.imd.service.impl;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.java.Log;
+import ufrn.imd.domain.Account;
+import ufrn.imd.domain.Client;
+import ufrn.imd.repository.Repository;
+import ufrn.imd.repository.impl.ClientRepository;
+import ufrn.imd.service.Service;
+import ufrn.imd.utils.ServerResponse;
+
+import java.rmi.RemoteException;
+import java.util.Optional;
+
+@Log
+@AllArgsConstructor
+public class TransferServiceImpl implements Service {
+
+    private final Repository<Client> clientRepository;
+
+    public ServerResponse transfer(Double value, Optional<Client> from, Optional<Account> to) throws RemoteException, RuntimeException {
+        Client fromUser = from.orElseThrow(() -> new RuntimeException("Null user!"));
+        Client fromClient = clientRepository.find(fromUser.getId())
+                .orElseThrow(() -> new RuntimeException("Invalid user!"));
+
+        Account toUserAccount = to.orElseThrow(() -> new RuntimeException("Null account"));
+        Client toClient = ((ClientRepository) clientRepository).findByAccountNumber(toUserAccount.getNumber())
+                .orElseThrow(() -> new RuntimeException(
+                        String.format("Customer not found with account number %s", toUserAccount.getNumber())));
+
+        if(fromClient.getId().equals(toClient.getId()))
+            throw new RuntimeException("Invalid account");
+
+        Account fromAccount = fromClient.getAccount();
+        if(value > fromAccount.getBalance()) throw new RuntimeException("Insufficient balance");
+
+        fromAccount.setBalance(fromAccount.getBalance() - value);
+        Account toAccount = toClient.getAccount();
+        toAccount.setBalance(toAccount.getBalance() + value);
+        log.info("Transfer concluded!");
+        log.info(String.format("Account balance: R$ %.2f", fromClient.getAccount().getBalance()));
+        return ServerResponse.builder()
+                .status(200)
+                .message("Operation sucessed!")
+                .body(fromClient.getAccount())
+                .build();
+    }
+}
diff --git a/banking-server/src/main/java/ufrn/imd/utils/NameSpace.java b/banking-server/src/main/java/ufrn/imd/utils/NameSpace.java
index d05657df43ae73e13b75ed8d0830f25e4be9910f..fe82fc880f2ddf63a9c7014be14a81ce89fc9c93 100644
--- a/banking-server/src/main/java/ufrn/imd/utils/NameSpace.java
+++ b/banking-server/src/main/java/ufrn/imd/utils/NameSpace.java
@@ -1,7 +1,7 @@
 package ufrn.imd.utils;
 
 public class NameSpace {
-
+    public static final Integer PORT_TRANSFER_SERVICE = 1909;
     public final static Integer PORT_BALANCE_SERVICE = 1908;
     public final static Integer PORT_DEPOSIT_SERVICE = 1907;
     public final static Integer PORT_WITHDRAWAL_SERVICE = 1906;
@@ -14,4 +14,7 @@ public class NameSpace {
 
     public final static String HOST_WITHDRAWAL_SERVICE =
             String.format("rmi://127.0.0.1:%d/%s", PORT_WITHDRAWAL_SERVICE, "withdrawal");
+
+    public final static String HOST_TRANSFER_SERVICE =
+            String.format("rmi://127.0.0.1:%d/%s", PORT_TRANSFER_SERVICE, "transfer");
 }
diff --git a/banking-server/src/main/java/ufrn/imd/utils/message/TransferMessage.java b/banking-server/src/main/java/ufrn/imd/utils/message/TransferMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..93fb4928759ad4746cd085a548fdcd6bbd28a4fe
--- /dev/null
+++ b/banking-server/src/main/java/ufrn/imd/utils/message/TransferMessage.java
@@ -0,0 +1,18 @@
+package ufrn.imd.utils.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import ufrn.imd.domain.Account;
+import ufrn.imd.domain.Client;
+
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+public class TransferMessage implements Serializable {
+    private static final long serialVersionUID = 2L;
+
+    private Client from;
+    private Account to;
+    private Double value;
+}
diff --git a/banking-server/target/classes/ufrn/imd/BankingServerApp.class b/banking-server/target/classes/ufrn/imd/BankingServerApp.class
index 84bf69c80fd2cd8f90878db02bd5836285daeaba..8d5ef782c69ac0f87e6afb4dd4b59b1497d69553 100644
Binary files a/banking-server/target/classes/ufrn/imd/BankingServerApp.class and b/banking-server/target/classes/ufrn/imd/BankingServerApp.class differ
diff --git a/banking-server/target/classes/ufrn/imd/repository/impl/ClientRepository.class b/banking-server/target/classes/ufrn/imd/repository/impl/ClientRepository.class
index 155a44b5c55392b0c43f96fcd159f827359a5777..c6d086468a406fbde73aefe262c8388575fe861e 100644
Binary files a/banking-server/target/classes/ufrn/imd/repository/impl/ClientRepository.class and b/banking-server/target/classes/ufrn/imd/repository/impl/ClientRepository.class differ
diff --git a/banking-server/target/classes/ufrn/imd/utils/NameSpace.class b/banking-server/target/classes/ufrn/imd/utils/NameSpace.class
index 615ca1f909796027ddf196e31bfa6a831963264c..42a6dfd302b25b75da9780c5ae89421c50754d76 100644
Binary files a/banking-server/target/classes/ufrn/imd/utils/NameSpace.class and b/banking-server/target/classes/ufrn/imd/utils/NameSpace.class differ