diff --git a/api-doc/reference/Admin-API.v1.yaml b/api-doc/reference/Admin-API.v1.yaml
index 9bb56b5ccde62a74c396cf6fb69d34c4e55f5328..5d4df4d67522a23fd146f9075c1e0593a9f0899e 100644
--- a/api-doc/reference/Admin-API.v1.yaml
+++ b/api-doc/reference/Admin-API.v1.yaml
@@ -17,6 +17,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Device'
+              examples: {}
       operationId: get-api-admin-device
       requestBody:
         description: ''
@@ -29,19 +30,41 @@ paths:
             type: string
           in: query
           name: deviceId
-      description: Returns the device information.
+      description: Returns the device detailed information.
     put:
       summary: ''
       operationId: put-api-admin-device
       responses:
         '200':
           description: OK
+        '500':
+          description: Internal Server Error
+      description: Update device data.
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: username
+        - schema:
+            type: string
+          in: query
+          name: deviceId
+        - schema:
+            type: string
+          in: query
+          name: deviceName
     delete:
       summary: ''
       operationId: delete-api-admin-device
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: './User-API.v1.yaml#/components/schemas/DeviceRevocationResponse'
+        '500':
+          description: Internal Server Error
       parameters:
         - schema:
             type: string
@@ -71,61 +94,161 @@ paths:
             type: string
           in: query
           name: username
+      description: Get a list of devices for a user.
   /api/admin/directory/entry:
-    get:
-      summary: Your GET endpoint
-      tags: []
-      responses:
-        '200':
-          description: OK
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/UserProfile'
-      operationId: get-api-admin-directory-entry
-      description: ''
     put:
       summary: ''
       operationId: put-api-admin-directory-entry
       responses:
         '200':
           description: OK
+      description: "Update a user's profile."
     post:
-      summary: ''
+      summary: User profile
       operationId: post-api-admin-directory-entry
       responses:
         '200':
           description: OK
+        '500':
+          description: Internal Server Error
+      description: Create a user profile.
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: directory
+    delete:
+      summary: ''
+      operationId: delete-api-admin-directory-entry
+      responses:
+        '200':
+          description: OK
+      description: Method might probably never be implemented.
   /api/admin/user:
     get:
-      summary: Your GET endpoint
+      summary: User profile - User
       tags: []
-      responses: {}
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UserProfile'
       operationId: get-api-admin-user
+      description: "Get the user's profile."
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: username
     post:
       summary: ''
       operationId: post-api-admin-user
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/User'
+      description: Create an internal user.
     delete:
       summary: ''
       operationId: delete-api-admin-user
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: './User-API.v1.yaml#/components/schemas/DeviceRevocationResponse'
+        '500':
+          description: Internal Server Error
+      description: Revoke a user.
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: username
     put:
       summary: ''
       operationId: put-api-admin-user
       responses:
         '200':
           description: OK
+        '500':
+          description: Internal Server Error
+      description: Update User data.
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: username
+        - schema:
+            type: string
+          in: query
+          name: password
   /api/admin/users:
     get:
-      summary: Your GET endpoint
+      summary: Users Profile
       tags: []
-      responses: {}
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/UserProfile'
       operationId: get-api-admin-users
+      description: Return a list of users.
+  /api/subscription:
+    get:
+      summary: Subscription status - License
+      tags: []
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SubscriptionStatusResponse'
+          headers:
+            Access-Control-Allow-Origin:
+              schema:
+                type: string
+              description: Server Domain of Certificate Authority
+      operationId: get-api-subscription
+      description: Get the subscription status.
+    post:
+      summary: ''
+      operationId: post-api-subscription
+      responses:
+        '200':
+          description: OK
+      description: 'Upload the license here, which is basically just uploading a base64 representation of the keypair - and store on disk.'
+  /api/update:
+    get:
+      summary: System Status
+      tags: []
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/FullSystemStatusResponse'
+      operationId: get-api-update
+      description: Return the current version number and the available version number of Jams(for update).
+    post:
+      summary: ''
+      operationId: post-api-update
+      responses:
+        '200':
+          description: OK
+      description: Update the version.
 components:
   schemas:
     Device:
@@ -164,3 +287,65 @@ components:
         organization:
           type: string
       description: "The user's extended information which is not critical to Jami operations, usually provided by LDAP, Active Directory or other backend."
+    User:
+      title: User
+      type: object
+      properties:
+        username:
+          type: string
+        password:
+          type: string
+        userType:
+          type: string
+          enum:
+            - AD
+            - LDAP
+            - LOCAL
+        realm:
+          type: string
+        accessLevel:
+          type: string
+          enum:
+            - ADMIN
+            - USER
+        needsPasswordReset:
+          type: boolean
+        ethAddress:
+          type: string
+        ethKey:
+          type: string
+        jamiId:
+          type: string
+    SubscriptionStatusResponse:
+      title: SubscriptionStatusResponse
+      type: object
+      properties:
+        licenseInformation:
+          $ref: '#/components/schemas/LicenseInformation'
+        activated:
+          type: boolean
+        versions:
+          type: object
+    LicenseInformation:
+      title: LicenseInformation
+      type: object
+      properties:
+        type:
+          type: string
+          enum:
+            - COMMUNITY
+            - PREMIUM
+        products:
+          type: array
+          items:
+            type: string
+    FullSystemStatusResponse:
+      title: FullSystemStatusResponse
+      type: object
+      properties:
+        localVersions:
+          type: object
+        remoteVersions:
+          type: object
+        updateAvailable:
+          type: boolean
diff --git a/api-doc/reference/Install-API.v1.yaml b/api-doc/reference/Install-API.v1.yaml
index 03b15027dd565d4523768b30618c33b3af4fbcc2..0e3c6958d078a65c7456f63f8589cb2c69531580 100644
--- a/api-doc/reference/Install-API.v1.yaml
+++ b/api-doc/reference/Install-API.v1.yaml
@@ -13,6 +13,20 @@ paths:
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/AuthTokenResponse'
+        '500':
+          description: Internal Server Error
+      description: 'Configure Server to use selected Authentication Source as authentication backend, save settings in config.json file.'
+    get:
+      summary: Authentication Source
+      operationId: get-api-install-auth
+      responses:
+        '200':
+          description: OK
+      description: "Get server's Authentication Source."
   /api/install/ca:
     post:
       summary: ''
@@ -20,6 +34,16 @@ paths:
       responses:
         '200':
           description: OK
+        '500':
+          description: Internal Server Error
+      description: Save Certificate Authority.
+    get:
+      summary: Certificate Request
+      operationId: get-api-install-ca
+      responses:
+        '200':
+          description: OK
+      description: Get Certificate Authority.
   /api/install/settings:
     post:
       summary: ''
@@ -27,6 +51,16 @@ paths:
       responses:
         '200':
           description: OK
+        '500':
+          description: Internal Server Error
+      description: Finish Server installation.
+    get:
+      summary: ''
+      operationId: get-api-install-settings
+      responses:
+        '200':
+          description: OK
+      description: Get Server Settings.
   /api/install/start:
     post:
       summary: ''
@@ -34,5 +68,52 @@ paths:
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/AuthTokenResponse'
+        '403':
+          description: Forbidden
+      description: Authenticate user.
+    get:
+      summary: ''
+      operationId: get-api-install-start
+      responses:
+        '200':
+          description: OK
+          headers:
+            showLogin:
+              schema:
+                type: boolean
+              description: 'true'
+      description: Check if user should login or sign-up.
+    put:
+      summary: ''
+      operationId: put-api-install-start
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/AuthTokenResponse'
+        '500':
+          description: Internal Server Error
+      description: Create administrative user account.
 components:
-  schemas: {}
+  schemas:
+    AuthTokenResponse:
+      title: AuthTokenResponse
+      type: object
+      properties:
+        token_type:
+          type: string
+        access_token:
+          type: string
+        expires_in:
+          type: number
+        scope:
+          type: string
+          enum:
+            - ADMIN
+            - USER
diff --git a/api-doc/reference/Nameserver-API.v1.yaml b/api-doc/reference/Nameserver-API.v1.yaml
index baec648acd279ccffc6982dde2375a150fde71fa..ae9de47f4fb8fb0b9f784282974d308c669fc393 100644
--- a/api-doc/reference/Nameserver-API.v1.yaml
+++ b/api-doc/reference/Nameserver-API.v1.yaml
@@ -16,8 +16,17 @@ paths:
     get:
       summary: Address lookup
       tags: []
-      responses: {}
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/AddrLookupResponse'
+        '404':
+          description: Not Found
       operationId: get-api-nameserver-addr-addr
+      description: Get Username from Adress.
   '/api/nameserver/name/{name}':
     parameters:
       - schema:
@@ -31,6 +40,31 @@ paths:
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/NameLookupResponse'
+        '404':
+          description: Not Found
       operationId: get-api-nameserver-name-name
+      description: Get Address from username.
 components:
-  schemas: {}
+  schemas:
+    AddrLookupResponse:
+      title: AddrLookupResponse
+      type: object
+      properties:
+        name:
+          type: string
+    NameLookupResponse:
+      title: NameLookupResponse
+      type: object
+      properties:
+        name:
+          type: string
+        addr:
+          type: string
+        publicKey:
+          type: string
+        signature:
+          type: string
diff --git a/api-doc/reference/Security-API.v1.yaml b/api-doc/reference/Security-API.v1.yaml
index 05e04371a9b6cb270e7d0e9da2c43d8a9f947117..0b8d608963b591e75322988f87a5afa3d105081b 100644
--- a/api-doc/reference/Security-API.v1.yaml
+++ b/api-doc/reference/Security-API.v1.yaml
@@ -12,5 +12,66 @@ paths:
       responses:
         '200':
           description: OK
+          content:
+            application/json:
+              schema:
+                $ref: './Install-API.v1.yaml#/components/schemas/AuthTokenResponse'
+        '403':
+          description: Forbidden
+      description: This method returns the token which is used for all the next calls to the API.
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: username
+        - schema:
+            type: string
+          in: query
+          name: password
+        - schema:
+            type: string
+          in: header
+          name: authorization
+  /api/auth/contacts:
+    get:
+      summary: User contacts
+      tags: []
+      responses: {}
+      operationId: get-api-auth-contacts
+      description: "Get User's contacts"
+    put:
+      summary: ''
+      operationId: put-api-auth-contacts
+      responses:
+        '200':
+          description: OK
+      description: "Update User's contact."
+    delete:
+      summary: ''
+      operationId: delete-api-auth-contacts
+      responses:
+        '200':
+          description: OK
+      description: "Delete user's contact."
+  /api/auth/ocsp:
+    get:
+      summary: OCSP
+      tags: []
+      responses: {}
+      operationId: get-api-auth-ocsp
+      description: Get OCSP.
+  /api/auth/crl:
+    get:
+      summary: CRL
+      tags: []
+      responses:
+        '200':
+          description: OK
+          content:
+            text/plain:
+              schema:
+                type: string
+      operationId: get-api-auth-crl
+      description: Get CRL.
 components:
   schemas: {}
diff --git a/api-doc/reference/User-API.v1.yaml b/api-doc/reference/User-API.v1.yaml
index 07b6a4c77b933afdd75ed1daade127caaaa78e9d..fa5e3f9e44a2b2786629907657ce9c2036052190 100644
--- a/api-doc/reference/User-API.v1.yaml
+++ b/api-doc/reference/User-API.v1.yaml
@@ -11,6 +11,21 @@ paths:
       tags: []
       responses: {}
       operationId: get-api-auth-contacts
+      description: "Get User's contacts."
+    put:
+      summary: ''
+      operationId: put-api-auth-contacts
+      responses:
+        '200':
+          description: OK
+      description: "Update User's contact."
+    delete:
+      summary: ''
+      operationId: delete-api-auth-contacts
+      responses:
+        '200':
+          description: OK
+      description: "Delete user's contact."
   '/api/auth/device/{deviceId}':
     parameters:
       - schema:
@@ -29,12 +44,21 @@ paths:
               schema:
                 $ref: './Admin-API.v1.yaml#/components/schemas/Device'
       operationId: get-api-auth-device-deviceId
+      description: "Get a user's specified device."
     put:
       summary: ''
       operationId: put-api-auth-device-deviceId
       responses:
         '200':
           description: OK
+        '500':
+          description: Internal Server Error
+      description: "Update a user's device informations."
+      parameters:
+        - schema:
+            type: string
+          in: query
+          name: deviceName
     post:
       summary: ''
       operationId: post-api-auth-device-deviceId
@@ -44,7 +68,23 @@ paths:
           content:
             application/json:
               schema:
-                allOf: []
+                $ref: '#/components/schemas/DeviceRegistrationResponse'
+        '500':
+          description: Internal Server Error
+      description: Create/Store a device for a user.
+    delete:
+      summary: ''
+      operationId: delete-api-auth-device-deviceId
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/DeviceRevocationResponse'
+        '500':
+          description: Internal Server Error
+      description: "Delete a user's device."
   /api/auth/devices:
     get:
       summary: Get the list of devices
@@ -59,12 +99,22 @@ paths:
                 items:
                   $ref: './Admin-API.v1.yaml#/components/schemas/Device'
       operationId: get-api-auth-devices
+      description: "Get user's devices."
   /api/auth/directories:
     get:
-      summary: Get the directories connect to JAMS
+      summary: "Get the directories connect to JAMS, Authentication Sources' Directories"
       tags: []
-      responses: {}
+      responses:
+        '200':
+          description: OK
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/AuthModuleKey'
       operationId: get-api-auth-directories
+      description: Get directories in Authentication Sources (Local/AD/LDAP).
   /api/auth/directory/entry:
     get:
       summary: Get the profile of a user
@@ -77,6 +127,14 @@ paths:
               schema:
                 $ref: './Admin-API.v1.yaml#/components/schemas/UserProfile'
       operationId: get-api-auth-directory-entry
+      description: 'This is an endpoint to manipulate directory entry-data, this make sense only for local setups. Get a user profile from a directory.'
+    put:
+      summary: ''
+      operationId: put-api-auth-directory-entry
+      responses:
+        '200':
+          description: OK
+      description: Modify a profile only in the case of a LOCAL directory.
   /api/auth/directory/search:
     get:
       summary: Search the directory
@@ -98,14 +156,65 @@ paths:
                 items:
                   $ref: './Admin-API.v1.yaml#/components/schemas/UserProfile'
       operationId: get-api-auth-directory-search
+      description: Search user profiles in directory.
   /api/auth/user:
     get:
       summary: User endpoint
       tags: []
-      responses: {}
+      responses:
+        '200':
+          description: OK
       operationId: get-api-auth-user
+      description: "Read user's profile (User can \"read\" his own profile)."
+    put:
+      summary: ''
+      operationId: put-api-auth-user
+      responses:
+        '200':
+          description: OK
+        '500':
+          description: Internal Server Error
+      description: "Update some user profile's fields(password, privatekey, publickey) if authentication source is LOCAL."
 components:
-  schemas: {}
+  schemas:
+    DeviceRegistrationResponse:
+      title: DeviceRegistrationResponse
+      type: object
+      properties:
+        certificateChain:
+          type: string
+        displayName:
+          type: string
+        nameServer:
+          type: string
+        deviceReceipt:
+          type: string
+        receiptSignature:
+          type: string
+        userPhoto:
+          type: string
+    DeviceRevocationResponse:
+      title: DeviceRevocationResponse
+      type: object
+      properties:
+        success:
+          type: boolean
+        errorDetails:
+          type: string
+        timestamp:
+          type: string
+    AuthModuleKey:
+      title: AuthModuleKey
+      type: object
+      properties:
+        realm:
+          type: string
+        type:
+          type: string
+          enum:
+            - AD
+            - LDAP
+            - LOCAL
   securitySchemes:
     API Key - 1:
       name: API Key
diff --git a/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java b/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
index ffbca27b868807ce98d7fc2ef74ebb7ab41c2904..06968295ad130f6b35e5404b570e5292a0795dec 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/AbstractDao.java
@@ -26,6 +26,7 @@ import lombok.Getter;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.datastore.main.DataStore;
+import net.jami.jams.common.dao.DeleteStatementBuilder;
 import net.jami.jams.common.dao.SelectStatementBuilder;
 import net.jami.jams.common.dao.StatementList;
 import net.jami.jams.common.dao.UpdateStatementBuilder;
@@ -34,7 +35,6 @@ import net.jami.jams.common.dao.connectivity.SQLConnection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
 
 @Slf4j
@@ -46,7 +46,6 @@ public abstract class AbstractDao<T> {
     private Class<T> tClass;
 
     public abstract boolean storeObject(T object);
-    public abstract boolean deleteObject(LinkedHashMap<String,String> constraints);
 
     public List<T> getObjects(StatementList constraints){
         List<T> result = new ArrayList<>();
@@ -82,4 +81,20 @@ public abstract class AbstractDao<T> {
             DataStore.connectionPool.returnConnection(connection);
         }
     }
+
+    public boolean deleteObject(StatementList delete){
+        SQLConnection connection = DataStore.connectionPool.getConnection();
+        try{
+            PreparedStatement ps = DeleteStatementBuilder.buildStatement(tableName,delete,connection);
+            return ps.execute();
+        }
+        catch (Exception e){
+            log.error("An error has occurred while trying to fetch a device: " + e.toString());
+            return false;
+        }
+        finally {
+            DataStore.connectionPool.returnConnection(connection);
+        }
+    }
+
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java b/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
index 1e33d86b870963fd13319a7f4ef1047d97fceb23..ac39587e242fdca3ef2aa509b661ac9e4c9abb22 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/ContactDao.java
@@ -22,25 +22,40 @@
 */
 package net.jami.datastore.dao;
 
-import net.jami.jams.common.dao.StatementList;
+import lombok.extern.slf4j.Slf4j;
+import net.jami.datastore.main.DataStore;
+import net.jami.jams.common.dao.connectivity.SQLConnection;
 import net.jami.jams.common.objects.contacts.Contact;
 
-import java.util.LinkedHashMap;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
 
+@Slf4j
 public class ContactDao extends AbstractDao<Contact> {
 
-    @Override
-    public boolean storeObject(Contact object) {
-        return false;
-    }
-
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
+    public ContactDao() {
+        SQLConnection connection = DataStore.connectionPool.getConnection();
+        try {
+            this.setTableName("contacts");
+            this.setTClass(Contact.class);
+            String createTable = "CREATE TABLE contacts (" +
+                "owner varchar(255), " +
+                "contact varchar(255)," +
+                "displayName varchar(255),"+
+                "PRIMARY KEY (owner,contact))";
+            PreparedStatement ps = connection.getConnection().prepareStatement(createTable);
+            ps.execute();
+        }
+        catch (SQLException e){
+            log.error("Could not create the contacts table with error " + e.getMessage());
+        }
+        finally {
+            DataStore.connectionPool.returnConnection(connection);
+        }
     }
 
     @Override
-    public boolean updateObject(StatementList update, StatementList constraints) {
+    public boolean storeObject(Contact object) {
         return false;
     }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java b/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
index 6af5941495ee0edb7f6a933f9a93004e25a63f06..2c5f897889c8d566fb347f71d3ad4bd6cd48fc54 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/DeviceDao.java
@@ -30,7 +30,6 @@ import net.jami.jams.common.objects.devices.Device;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
 public class DeviceDao extends AbstractDao<Device> {
@@ -78,11 +77,6 @@ public class DeviceDao extends AbstractDao<Device> {
         }
     }
 
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
-
     @Override
     public boolean updateObject(StatementList update, StatementList constraints) {
         return false;
diff --git a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
index 7cb9e1587a8ab624870a486a862c109cc27722be..5f0a9df589064180e6866e4ea64f032ed5a4744b 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/SystemDao.java
@@ -30,7 +30,6 @@ import net.jami.jams.common.objects.system.SystemAccount;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
 public class SystemDao extends AbstractDao<SystemAccount> {
@@ -76,11 +75,6 @@ public class SystemDao extends AbstractDao<SystemAccount> {
         }
     }
 
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
-
     @Override
     public boolean updateObject(StatementList update, StatementList constraints) {
         return false;
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
index e5b75b84902df1a90abb9fd8f39c77c4985d5ac6..2c46552e98c53678012531bed779b92f4a337e7b 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserDao.java
@@ -29,7 +29,6 @@ import net.jami.jams.common.objects.user.User;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
 public class UserDao extends AbstractDao<User> {
@@ -83,10 +82,4 @@ public class UserDao extends AbstractDao<User> {
             DataStore.connectionPool.returnConnection(connection);
         }
     }
-
-
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDAO.java b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
similarity index 90%
rename from datastore/src/main/java/net/jami/datastore/dao/UserProfileDAO.java
rename to datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
index 1f1d4096fde5916969f9a52fb243c8ca9231d854..e2df45111a4afc700662fdea0e68558306ca559e 100644
--- a/datastore/src/main/java/net/jami/datastore/dao/UserProfileDAO.java
+++ b/datastore/src/main/java/net/jami/datastore/dao/UserProfileDao.java
@@ -29,13 +29,12 @@ import net.jami.jams.common.objects.user.UserProfile;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.LinkedHashMap;
 
 @Slf4j
-public class UserProfileDAO extends AbstractDao<UserProfile> {
+public class UserProfileDao extends AbstractDao<UserProfile> {
 
     //Fis this to include the fields from AD/LDAP.
-    public UserProfileDAO() {
+    public UserProfileDao() {
         SQLConnection connection = DataStore.connectionPool.getConnection();
         try {
             this.setTableName("local_directory");
@@ -60,9 +59,4 @@ public class UserProfileDAO extends AbstractDao<UserProfile> {
     public boolean storeObject(UserProfile object) {
         return false;
     }
-
-    @Override
-    public boolean deleteObject(LinkedHashMap<String, String> constraints) {
-        return false;
-    }
 }
diff --git a/datastore/src/main/java/net/jami/datastore/main/DataStore.java b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
index 41ed66eefbed2b3d301b0ed153d381eab663ba7f..852cdaeafea5f50450e8183b5342a1c0decf2418 100644
--- a/datastore/src/main/java/net/jami/datastore/main/DataStore.java
+++ b/datastore/src/main/java/net/jami/datastore/main/DataStore.java
@@ -24,6 +24,7 @@ package net.jami.datastore.main;
 
 import lombok.Getter;
 import lombok.Setter;
+import net.jami.datastore.dao.ContactDao;
 import net.jami.datastore.dao.DeviceDao;
 import net.jami.datastore.dao.SystemDao;
 import net.jami.datastore.dao.UserDao;
@@ -46,6 +47,7 @@ public class DataStore implements AuthenticationSource {
     private UserDao userDao;
     private DeviceDao deviceDao;
     private SystemDao systemDao;
+    private ContactDao contactDao;
 
     //Implicitly connect to debry.
     public DataStore(String connectionString) {
@@ -53,6 +55,7 @@ public class DataStore implements AuthenticationSource {
         userDao = new UserDao();
         deviceDao = new DeviceDao();
         systemDao = new SystemDao();
+        contactDao = new ContactDao();
     }
 
     public boolean userExists(String username){
diff --git a/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java b/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c3d05f6edd63e10845b5ea6e26975c3ab194a5c
--- /dev/null
+++ b/jams-common/src/main/java/net/jami/jams/common/dao/DeleteStatementBuilder.java
@@ -0,0 +1,60 @@
+/*
+* Copyright (C) 2020 by Savoir-faire Linux
+* Authors: William Enright <william.enright@savoirfairelinux.com>
+*          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com>
+*          Johnny Flores <johnny.flores@savoirfairelinux.com>
+*          Mohammed Raza <mohammed.raza@savoirfairelinux.com>
+*          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com>
+*
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+package net.jami.jams.common.dao;
+
+import net.jami.jams.common.dao.connectivity.SQLConnection;
+
+import java.sql.PreparedStatement;
+
+public class DeleteStatementBuilder {
+
+    public static PreparedStatement buildStatement(String table, StatementList statementElements,
+                                                   SQLConnection connection) throws Exception {
+        PreparedStatement ps = null;
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("DELETE FROM ").append(table);
+        if(statementElements != null) {
+            stringBuilder.append(" WHERE ");
+            for (StatementElement statementElement : statementElements.getStatements()) {
+                stringBuilder
+                    .append(statementElement.getColumn())
+                    .append(" ")
+                    .append(statementElement.getOperator())
+                    .append(" ")
+                    .append("?")
+                    .append(" ")
+                    .append(statementElement.getNextStatementRelation());
+            }
+            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
+            int i = 1;
+            for (StatementElement statementElement : statementElements.getStatements()) {
+                ps.setString(i, statementElement.getValue());
+                i++;
+            }
+        }
+        else{
+            ps = connection.getConnection().prepareStatement(stringBuilder.toString());
+        }
+        return ps;
+    }
+}
diff --git a/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java b/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java
index 2804fd9605299b4dbd70e598aaf4c8e4388388a2..dfcf11b391b0b0dcc43ead99a63f88183f40affa 100644
--- a/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java
+++ b/jams-common/src/main/java/net/jami/jams/common/objects/contacts/Contact.java
@@ -22,10 +22,46 @@
 */
 package net.jami.jams.common.objects.contacts;
 
+import com.jsoniter.annotation.JsonIgnore;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
+import net.jami.jams.common.serialization.database.DatabaseObject;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 
 @Getter
 @Setter
-public class Contact {
+@NoArgsConstructor
+public class Contact implements DatabaseObject {
+
+    @JsonIgnore //Ignore the owner because he is irrelevant.
+    private String owner;
+    private String uri;
+    private String displayName;
+
+    public Contact(ResultSet rs) throws Exception {
+        this.owner = rs.getString("owner");
+        this.uri = rs.getString("uri");
+        this.displayName = rs.getString("displayName");
+    }
+
+    @Override
+    public PreparedStatement getInsert(PreparedStatement ps) throws Exception {
+        ps.setString(1,owner);
+        ps.setString(2,uri);
+        ps.setString(3,displayName);
+        return ps;
+    }
+
+    @Override
+    public PreparedStatement getDelete(PreparedStatement ps) throws Exception {
+        return null;
+    }
+
+    @Override
+    public PreparedStatement getUpdate(PreparedStatement ps) throws Exception {
+        return null;
+    }
 }
diff --git a/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java b/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java
index 2198d8cac27346ea957e9460e74004d02eedf541..0489430e839adb39190231da637a55253987d813 100644
--- a/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java
+++ b/jams-common/src/main/java/net/jami/jams/common/serialization/database/DatabaseObject.java
@@ -25,7 +25,6 @@ package net.jami.jams.common.serialization.database;
 import java.sql.PreparedStatement;
 
 public interface DatabaseObject {
-
     PreparedStatement getInsert(PreparedStatement ps) throws Exception;
     PreparedStatement getDelete(PreparedStatement ps) throws Exception;
     PreparedStatement getUpdate(PreparedStatement ps) throws Exception;
diff --git a/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java b/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java
index 814a9658155dba0b3b700873d995c33e761e7fda..863b549c20bbedc4ea70d63d1633de73135e775a 100644
--- a/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java
+++ b/jams-server/src/main/java/net/jami/jams/server/core/TomcatLauncher.java
@@ -23,7 +23,6 @@
 package net.jami.jams.server.core;
 
 import lombok.extern.slf4j.Slf4j;
-import net.jami.jams.server.Server;
 import org.apache.catalina.WebResourceRoot;
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.core.StandardContext;
@@ -36,8 +35,6 @@ import org.apache.tomcat.util.descriptor.web.ErrorPage;
 import java.awt.*;
 import java.io.File;
 import java.net.URI;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
index 9b0626fde9b5bb026e0ac1caa672ac7128dfb703..e43a40d46f0535fba9b314d60ca0092882189816 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/api/auth/contacts/ContactServlet.java
@@ -22,28 +22,48 @@
 */
 package net.jami.jams.server.servlets.api.auth.contacts;
 
+import com.jsoniter.JsonIterator;
+import com.jsoniter.output.JsonStream;
+import net.jami.jams.common.dao.StatementElement;
+import net.jami.jams.common.dao.StatementList;
+import net.jami.jams.common.objects.contacts.Contact;
+
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.util.List;
+
+import static net.jami.jams.server.Server.dataStore;
 
 @WebServlet("/api/auth/contacts")
 public class ContactServlet extends HttpServlet {
 
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        super.doGet(req, resp);
+        StatementList statementList = new StatementList();
+        statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),""));
+        List<Contact> contactList = dataStore.getContactDao().getObjects(statementList);
+        resp.getOutputStream().write(JsonStream.serialize(contactList).getBytes());
     }
 
     @Override
     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        super.doPut(req, resp);
+        Contact contact = JsonIterator.deserialize(req.getInputStream().readAllBytes(),Contact.class);
+        contact.setOwner(req.getAttribute("username").toString());
+        if(dataStore.getContactDao().storeObject(contact)) resp.setStatus(200);
+        else resp.sendError(500,"Could not store device!");
     }
 
+    //TODO: Because deleting requires sending the URI in the body, didn't want to do this now.
     @Override
     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        super.doDelete(req, resp);
+        StatementList statementList = new StatementList();
+        statementList.addStatement(new StatementElement("owner","=",req.getAttribute("username").toString(),"AND"));
+        statementList.addStatement(new StatementElement("uri","=",req.getParameter("uri"),""));
+        if(dataStore.getContactDao().deleteObject(statementList)) resp.setStatus(200);
+        else resp.sendError(500,"Could not delete a contact!");
     }
 }
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java
index 0cf7d3fcf3322820d97b2183eb57e537ad939fdd..de794eb1ab865ad8f858e70f04a516a034320b32 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/AdminApiFilter.java
@@ -25,16 +25,16 @@ package net.jami.jams.server.servlets.filters;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jwt.SignedJWT;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.annotation.WebFilter;
 import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.common.objects.user.AccessLevel;
 import net.jami.jams.server.Server;
 
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java
index a125c4e4e5aab338a623bb974f8a3607350f5f06..2ab0ce4d7fdb81f40d0a364a0768cc6f9445bbe2 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/ApiFilter.java
@@ -25,15 +25,15 @@ package net.jami.jams.server.servlets.filters;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jwt.SignedJWT;
+import lombok.extern.slf4j.Slf4j;
+import net.jami.jams.server.Server;
+
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.annotation.WebFilter;
-import lombok.extern.slf4j.Slf4j;
-import net.jami.jams.server.Server;
-
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
diff --git a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java
index af6c2d9a52b189c490a5cd7f215dbc49252fea3c..68e1a23558f34967757794399e01929215553885 100644
--- a/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java
+++ b/jams-server/src/main/java/net/jami/jams/server/servlets/filters/InstallFilter.java
@@ -25,15 +25,15 @@ package net.jami.jams.server.servlets.filters;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jwt.SignedJWT;
+import lombok.extern.slf4j.Slf4j;
+import net.jami.jams.server.Server;
+
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.annotation.WebFilter;
-import lombok.extern.slf4j.Slf4j;
-import net.jami.jams.server.Server;
-
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;