diff --git a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/TokenEndpoint.java b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/TokenEndpoint.java
index 7a7bea971b29ef7dab1303f03db4da485c74ec81..a9218dd66a5b08ac1016264163663a75d0024eb5 100644
--- a/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/TokenEndpoint.java
+++ b/fda-authentication-service/rest-service/src/main/java/at/tuwien/endpoints/TokenEndpoint.java
@@ -84,16 +84,17 @@ public class TokenEndpoint {
                 .body(dto);
     }
 
-    @DeleteMapping("/{hash}")
+    @DeleteMapping("/{id}")
     @Transactional
     @Timed(value = "token.delete", description = "Time needed to delete the developer tokens")
     @Operation(summary = "Delete developer token", security = @SecurityRequirement(name = "bearerAuth"))
-    public void delete(@NotNull @PathVariable("hash") String hash,
+    public void delete(@NotNull @PathVariable("id") Long id,
                        @NotNull Principal principal) throws TokenNotFoundException, UserNotFoundException {
-        log.debug("endpoint delete developer token, hash={}, principal={}", hash, principal);
-        final Token token = tokenService.findOne(hash);
+        log.debug("endpoint delete developer token, id={}, principal={}", id, principal);
+        final Token token = tokenService.findOne(id);
         log.trace("found token {}", token);
         tokenService.delete(token.getTokenHash(), principal);
+        log.info("Deleted token with id {}", id);
     }
 
 }
\ No newline at end of file
diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/service/TokenService.java b/fda-authentication-service/services/src/main/java/at/tuwien/service/TokenService.java
index 4915baaf36e2a7e3b2d1845ad94ccf7047d91483..caeeb8d41f9532c40b167a6758c8f5e542355d12 100644
--- a/fda-authentication-service/services/src/main/java/at/tuwien/service/TokenService.java
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/service/TokenService.java
@@ -42,6 +42,15 @@ public interface TokenService {
      */
     Token findOne(String tokenHash) throws TokenNotFoundException;
 
+    /**
+     * Finds a token by id.
+     *
+     * @param id The token id.
+     * @return The token, if successful.
+     * @throws TokenNotFoundException The token was not found in the metadata database.
+     */
+    Token findOne(Long id) throws TokenNotFoundException;
+
     /**
      * Deletes a developer token in the metadata database by hash and user principal.
      *
diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/TokenServiceImpl.java b/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/TokenServiceImpl.java
index 33456b3299ffb8c6967251c8ff2a233f14b1669d..534e3727dcf3fc97810770710fd9451956dd7a4f 100644
--- a/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/TokenServiceImpl.java
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/TokenServiceImpl.java
@@ -81,6 +81,17 @@ public class TokenServiceImpl implements TokenService {
         return optional.get();
     }
 
+    @Override
+    @Transactional(readOnly = true)
+    public Token findOne(Long id) throws TokenNotFoundException {
+        final Optional<Token> optional = tokenRepository.findById(id);
+        if (optional.isEmpty()) {
+            log.error("Failed to find token with id {}", id);
+            throw new TokenNotFoundException("Failed to find token");
+        }
+        return optional.get();
+    }
+
     @Override
     @Transactional
     public void delete(String tokenHash, Principal principal) throws TokenNotFoundException, UserNotFoundException {
diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/Token.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/Token.java
index 17811e2efec89e48b290977818db22cb51212c59..44ee9ba94412e6ef1405af32223414f028d3d0f7 100644
--- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/Token.java
+++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/Token.java
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 import org.hibernate.annotations.GenericGenerator;
 import org.hibernate.annotations.SQLDelete;
+import org.hibernate.annotations.Where;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.jpa.domain.support.AuditingEntityListener;
 
diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue
index 63c821f9eed411adbe629b3af998f1f07b0c4cd0..919a3359c3cc76f21e02575667be36cb98e5ac7c 100644
--- a/fda-ui/layouts/default.vue
+++ b/fda-ui/layouts/default.vue
@@ -263,8 +263,8 @@ export default {
       }
     },
     login () {
-      let redirect = ![undefined ,'/', '/login'].includes(this.$router.currentRoute.path)
-      this.$router.push({ path: '/login', query: redirect ? { redirect: this.$router.currentRoute.path } : {}})
+      const redirect = ![undefined, '/', '/login'].includes(this.$router.currentRoute.path)
+      this.$router.push({ path: '/login', query: redirect ? { redirect: this.$router.currentRoute.path } : {} })
     },
     navigate (item) {
       this.$router.push(this.metadata(item).link)
diff --git a/fda-ui/nuxt.config.js b/fda-ui/nuxt.config.js
index 08afe5b2e157211bc6a6352dd5343badea42db39..902ab4c355e844468c25af4a737178b917ab9560 100644
--- a/fda-ui/nuxt.config.js
+++ b/fda-ui/nuxt.config.js
@@ -77,7 +77,8 @@ export default {
     sharedFilesystem: process.env.SHARED_FILESYSTEM || '/tmp',
     version: process.env.VERSION || 'latest',
     logo: process.env.LOGO || '/logo.png',
-    mailVerify: process.env.MAIL_VERIFY || false
+    mailVerify: process.env.MAIL_VERIFY || false,
+    tokenMax: process.env.TOKEN_MAX || 5
   },
 
   proxy: {
diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue
index b9b82425b216eb84ac34d9bedfbdef1765e72778..caf8bf208eb8768656cd7a62bccc8f5ea3af974d 100644
--- a/fda-ui/pages/login.vue
+++ b/fda-ui/pages/login.vue
@@ -96,7 +96,7 @@ export default {
         delete user.token
         this.$store.commit('SET_USER', user)
         this.$toast.success('Welcome back!')
-        this.$router.push(this.$route.query.redirect ?  this.$route.query.redirect : '/container')
+        this.$router.push(this.$route.query.redirect ? this.$route.query.redirect : '/container')
       } catch (err) {
         if (err.response !== undefined && err.response.status !== undefined) {
           if (err.response.status === 418) {
diff --git a/fda-ui/pages/user/developer.vue b/fda-ui/pages/user/developer.vue
index bdc5f38bfe235be6489c3348793df1be5390645f..9dc9bf35fade6bf5784ef4116e9b62a69c0646e8 100644
--- a/fda-ui/pages/user/developer.vue
+++ b/fda-ui/pages/user/developer.vue
@@ -9,9 +9,10 @@
           <v-card-text>
             <v-list-item v-for="(item, i) in tokens" :key="i" three-line>
               <v-list-item-content>
-                <v-list-item-title>sha256:{{ item.token_hash }}</v-list-item-title>
-                <v-list-item-subtitle v-if="!item.token">
-                  Created on {{ format(item.created) }}, Valid until: {{ format(item.expires) }}</v-list-item-subtitle>
+                <v-list-item-title :class="tokenClass(item)">sha256:{{ item.token_hash }}</v-list-item-title>
+                <v-list-item-subtitle v-if="!item.token" :class="tokenClass(item)">
+                  Last used: <span v-if="item.last_used">{{ format(item.last_used) }}</span><span v-if="!item.last_used">Never</span> &mdash; valid until: {{ format(item.expires) }}
+                </v-list-item-subtitle>
                 <v-list-item-subtitle v-if="item.token">
                   <v-text-field
                     v-model="item.token"
@@ -23,12 +24,12 @@
                     @click:append-outer="copy(item)" />
                 </v-list-item-subtitle>
                 <v-list-item-subtitle v-if="!item.token">
-                  <a @click="revokeToken(item.token_hash)">Revoke Token</a>
+                  <a @click="revokeToken(item.id)">Revoke Token</a>
                 </v-list-item-subtitle>
               </v-list-item-content>
             </v-list-item>
-            <v-btn class="mt-4" x-small @click="mintToken">
-              Mint Token
+            <v-btn :disabled="tokens.length >= tokenMax" class="mt-4" color="secondary" small @click="mintToken">
+              Create Token
             </v-btn>
           </v-card-text>
         </v-card>
@@ -59,6 +60,9 @@ export default {
       return {
         headers: { Authorization: `Bearer ${this.token}` }
       }
+    },
+    tokenMax () {
+      return this.$config.tokenMax
     }
   },
   mounted () {
@@ -74,6 +78,9 @@ export default {
     format (timestamp) {
       return formatTimestamp(timestamp)
     },
+    tokenClass (token) {
+      return token.last_used ? '' : 'token-not_used'
+    },
     async loadTokens () {
       this.loading = true
       try {
@@ -102,10 +109,10 @@ export default {
       }
       this.loading = false
     },
-    async revokeToken (hash) {
+    async revokeToken (id) {
       this.loading = true
       try {
-        await this.$axios.delete(`/api/user/token/${hash}`, this.config)
+        await this.$axios.delete(`/api/user/token/${id}`, this.config)
         await this.loadTokens()
       } catch (err) {
         this.$toast.error('Could not delete token')
@@ -115,3 +122,8 @@ export default {
   }
 }
 </script>
+<style>
+.token-not_used {
+  opacity: 0.4;
+}
+</style>