diff --git a/oidc-controller/api/authSessions/models.py b/oidc-controller/api/authSessions/models.py
index 8e10ec6d..c8fdc257 100644
--- a/oidc-controller/api/authSessions/models.py
+++ b/oidc-controller/api/authSessions/models.py
@@ -15,6 +15,7 @@ class AuthSessionState(StrEnum):
     EXPIRED = auto()
     VERIFIED = auto()
     FAILED = auto()
+    ABANDONED = auto()
 
 class AuthSessionBase(BaseModel):
     pres_exch_id: str
diff --git a/oidc-controller/api/routers/acapy_handler.py b/oidc-controller/api/routers/acapy_handler.py
index b53ff642..53a06737 100644
--- a/oidc-controller/api/routers/acapy_handler.py
+++ b/oidc-controller/api/routers/acapy_handler.py
@@ -61,6 +61,16 @@ async def post_topic(request: Request, topic: str, db: Database = Depends(get_db
                 await AuthSessionCRUD(db).patch(
                     str(auth_session.id), AuthSessionPatch(**auth_session.dict())
                 )
+            
+            # abandoned state
+            if webhook_body["state"] == "abandoned":
+                logger.info("ABANDONED")
+                logger.info(webhook_body["error_msg"])
+                auth_session.proof_status = AuthSessionState.ABANDONED
+                await sio.emit("status", {"status": "abandoned"}, to=sid)
+                await AuthSessionCRUD(db).patch(
+                    str(auth_session.id), AuthSessionPatch(**auth_session.dict())
+                )
 
             # Calcuate the expiration time of the proof
             now_time = datetime.now()
diff --git a/oidc-controller/api/templates/verified_credentials.html b/oidc-controller/api/templates/verified_credentials.html
index 38a667d8..c1075fbf 100644
--- a/oidc-controller/api/templates/verified_credentials.html
+++ b/oidc-controller/api/templates/verified_credentials.html
@@ -136,6 +136,7 @@
       .header-desc.success,
       .header-desc.pending,
       .header-desc.expired,
+      .header-desc.abandoned,
       .header-desc.failed {
         display: none;
         border-radius: 0.5rem;
@@ -166,6 +167,9 @@
       .header-desc.success {
         background-color: #dff0d8;
       }
+      .header-desc.abandoned {
+        background-color: #f2dede;
+      }
       .header-desc a {
         line-height: 1rem;
       }
@@ -216,6 +220,18 @@ <h1>Scan with a Digital Wallet</h1>
           </div>
         </div>
 
+        <div class="header-desc abandoned">
+           <div class="qr-code-image">{{add_asset("circle-x.svg")}}</div>
+           <div class="qr-code-desc">
+             <b>Proof declined</b>
+             </br>
+             <a href="javascript:window.location.reload(true)"
+              title="Refresh QR code."
+               >Try again.</a
+             >
+           </div>
+         </div>
+
         <div class="header-desc pending">
           <div class="qr-code-image">{{add_asset("hourglass.svg")}}</div>
           <div class="qr-code-desc">
@@ -273,93 +289,27 @@ <h1>Scan with a Digital Wallet</h1>
     socket.connect();
 
     const toggleState = (state) => {
-      const intro = document.querySelector(".intro");
-      const success = document.querySelector(".success");
-      const pending = document.querySelector(".pending");
-      const failed = document.querySelector(".failed");
-      const expired = document.querySelector(".expired");
-      const qrcode = document.querySelector(".qr-code");
-      const scannedMask = document.querySelector(".scanned-mask");
-      const refreshButton = document.getElementById("refresh-button");
-
       switch (state) {
         case "intro":
-          // Header elements
-          intro.style.display = "grid";
-          success.style.display = "none";
-          pending.style.display = "none";
-          failed.style.display = "none";
-          expired.style.display = "none";
-
-          // Button elements
-          refreshButton.style.display = "none";
-
-          // Turn off the spinner
-          qrcode.classList.remove("pending");
+          setUiElements(".intro", false, false, false);
           break;
         case "verified":
-          // Header elements
-          intro.style.display = "none";
-          success.style.display = "grid";
-          pending.style.display = "none";
-          failed.style.display = "none";
-          expired.style.display = "none";
-
-          // Button elements
-          refreshButton.style.display = "none";
-          scannedMask.style.display = "flex";
-
-          // Turn off the spinner
-          qrcode.classList.remove("pending");
-
+          setUiElements(".success", false, true, false);
           setTimeout(() => {
             window.location.replace("{{callback_url}}", { method: "POST" });
           }, 2000);
           break;
         case "failed":
-          // Header elements
-          intro.style.display = "none";
-          success.style.display = "none";
-          pending.style.display = "none";
-          failed.style.display = "grid";
-          expired.style.display = "none";
-
-          // Button elements
-          refreshButton.style.display = "flex";
-          scannedMask.style.display = "none";
-
-          // Turn off the spinner
-          qrcode.classList.remove("pending");
+          setUiElements(".failed", true, false, false);
           break;
         case "pending":
-          // Header elements
-          intro.style.display = "none";
-          success.style.display = "none";
-          pending.style.display = "grid";
-          failed.style.display = "none";
-          expired.style.display = "none";
-
-          // Button elements
-          refreshButton.style.display = "none";
-          scannedMask.style.display = "flex";
-
-          // Turn on the spinner
-          qrcode.classList.add("pending");
+          setUiElements(".pending", false, true, true);
           break;
         case "expired":
-          // Header elements
-          intro.style.display = "none";
-          success.style.display = "none";
-          pending.style.display = "none";
-          failed.style.display = "none";
-          expired.style.display = "grid";
-
-          // Button elements
-          refreshButton.style.display = "flex";
-          scannedMask.style.display = "none";
-
-          // Turn off the spinner
-          qrcode.classList.remove("pending");
+          setUiElements(".expired", true, false, false);
+          break;
+        case "abandoned":
+          setUiElements(".abandoned", true, false, false);
           break;
         }
     };
@@ -368,6 +318,29 @@ <h1>Scan with a Digital Wallet</h1>
       location.reload(true);
     });
 
+    /**
+     * Set the UI elements based on the current state
+     */
+    const setUiElements = (state, showRefresh, showScanned, setSpinner) => {
+      const stateElement = document.querySelector(state);
+      const qrcode = document.querySelector(".qr-code");
+      const scannedMask = document.querySelector(".scanned-mask");
+      const refreshButton = document.getElementById("refresh-button");
+
+      // set all elements to display: none and display the current state
+      document.querySelectorAll(".header-desc").forEach((el) => {
+        el.style.display = "none";
+      });
+      stateElement.style.display = "grid";
+
+      // set the refresh and/or scanned overlays
+      refreshButton.style.display = showRefresh ? "flex" : "none";
+      scannedMask.style.display = showScanned ? "flex" : "none";
+
+      // add or remove 'pending' class from qrcode based on setSpinner
+      qrcode.classList.toggle("pending", setSpinner);
+    }
+
     let timer;
 
     /**