diff --git a/.env.example b/.env.example
index 436b0a3f9a76c8e99d9ca8b0c25135f49393b7cb..8a5410b5826ad3f7d72c0a2ea6da677d8a0c347d 100644
--- a/.env.example
+++ b/.env.example
@@ -1,3 +1,4 @@
 DATABASE_URL=jdbc:mysql://{host??}:{port??}/{database_name??}
 DATABASE_USERNAME=
-DATABASE_PASSWORD=
\ No newline at end of file
+DATABASE_PASSWORD=
+API_KEY=
\ No newline at end of file
diff --git a/src/main/java/org/tonality/service/BaseWebService.java b/src/main/java/org/tonality/service/BaseWebService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ac46692eb86a94fc352c78a56db906a3acecf08
--- /dev/null
+++ b/src/main/java/org/tonality/service/BaseWebService.java
@@ -0,0 +1,39 @@
+package org.tonality.service;
+
+import javax.annotation.Resource;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpExchange;
+
+// https://stackoverflow.com/questions/12727989/jax-ws-getting-client-ip/13693024#13693024
+public abstract class BaseWebService {
+    @Resource
+    protected javax.xml.ws.WebServiceContext context;
+
+    protected final String httpExchangeKey = "com.sun.xml.internal.ws.http.exchange";
+
+    protected String getClientIp() {
+        MessageContext messageContext = context.getMessageContext();
+        HttpExchange exchange = (HttpExchange) messageContext.get(httpExchangeKey);
+        return exchange.getRemoteAddress().getAddress().getHostAddress();
+    }
+
+    protected String getClientApiKey() {
+        MessageContext messageContext = context.getMessageContext();
+        HttpExchange exchange = (HttpExchange) messageContext.get(httpExchangeKey);
+        return exchange.getRequestHeaders().getFirst("X-API-KEY");
+    }
+
+    protected boolean isRequestValid() {
+        return getClientApiKey() != null && getClientApiKey().equals(System.getenv("API_KEY"));
+    }
+
+    protected void logRequest() throws Exception {
+        if (!isRequestValid()) throw new Exception("Invalid request");
+        // TODO : implement logging to database
+        System.out.println("Client IP: " + getClientIp());
+        System.out.println("Client API Key: " + getClientApiKey());
+    }
+}
diff --git a/src/main/java/org/tonality/service/Subscription.java b/src/main/java/org/tonality/service/Subscription.java
index 70632093564810dfc6f812cadd6cfeccd98d437f..ead0701d44847499f813c72f29dac874f835ef5d 100644
--- a/src/main/java/org/tonality/service/Subscription.java
+++ b/src/main/java/org/tonality/service/Subscription.java
@@ -7,10 +7,11 @@ import javax.jws.WebService;
 import java.util.List;
 
 @WebService(endpointInterface = "org.tonality.service.ISubscription")
-public class Subscription implements ISubscription {
+public class Subscription extends BaseWebService implements ISubscription {
     @Override
     public org.tonality.model.Subscription createSubscription(long userId, String username, long albumId, String albumName, String artist) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().createSubscription(userId, username, albumId, albumName, artist);
         } catch (Exception e) {
             e.printStackTrace();
@@ -21,6 +22,7 @@ public class Subscription implements ISubscription {
     @Override
     public org.tonality.model.Subscription updateSubscription(long userId, long albumId, SubscriptionStatus status) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().updateSubscription(userId, albumId, status);
         } catch (Exception e) {
             e.printStackTrace();
@@ -31,6 +33,7 @@ public class Subscription implements ISubscription {
     @Override
     public org.tonality.model.Subscription getSubscription(long userId, long albumId) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().getById(new SubscriptionId(userId, albumId));
         } catch (Exception e) {
             e.printStackTrace();
@@ -41,6 +44,7 @@ public class Subscription implements ISubscription {
     @Override
     public List<org.tonality.model.Subscription> searchSubscription(SubscriptionStatus status, String searchInput, String orderBy, int page, int size) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().searchSubscriptions(status, searchInput, orderBy, page, size);
         } catch (Exception e) {
             e.printStackTrace();
@@ -51,6 +55,7 @@ public class Subscription implements ISubscription {
     @Override
     public List<org.tonality.model.Subscription> getSubscriptionsByStatus(SubscriptionStatus status, String orderBy, int page, int size) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().getSubscriptionByStatus(status, orderBy, page, size);
         } catch (Exception e) {
             e.printStackTrace();
@@ -61,6 +66,7 @@ public class Subscription implements ISubscription {
     @Override
     public List<org.tonality.model.Subscription> getSubscriptionsByUserId(long userId, int page, int size) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().getSubscriptionsByUserId(userId, page, size);
         } catch (Exception e) {
             e.printStackTrace();
@@ -71,6 +77,7 @@ public class Subscription implements ISubscription {
     @Override
     public boolean deleteSubscription(long userId, long albumId) {
         try {
+            logRequest();
             if (!org.tonality.repository.Subscription.getInstance().deleteById(new org.tonality.model.SubscriptionId(userId, albumId))) {
                 throw new Exception("Failed to delete subscription");
             }
@@ -84,6 +91,7 @@ public class Subscription implements ISubscription {
     @Override
     public boolean deleteSubscriptionsByUserId(long userId) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().deleteSubscriptionsByUserId(userId);
         } catch (Exception e) {
             e.printStackTrace();
@@ -94,6 +102,7 @@ public class Subscription implements ISubscription {
     @Override
     public boolean deleteSubscriptionsByAlbumId(long albumId) {
         try {
+            logRequest();
             return org.tonality.repository.Subscription.getInstance().deleteSubscriptionsByAlbumId(albumId);
         } catch (Exception e) {
             e.printStackTrace();