diff --git a/libs/client/src/application.rs b/libs/client/src/application.rs
new file mode 100644
index 000000000..6fb611c27
--- /dev/null
+++ b/libs/client/src/application.rs
@@ -0,0 +1,19 @@
+use crate::{ClientError, KanidmClient};
+use kanidm_proto::scim_v1::client::{ScimEntryApplication, ScimEntryApplicationPost};
+
+impl KanidmClient {
+    /// Delete an application
+    pub async fn idm_application_delete(&self, id: &str) -> Result<(), ClientError> {
+        self.perform_delete_request(format!("/scim/v1/Application/{}", id).as_str())
+            .await
+    }
+
+    /// Create an application
+    pub async fn idm_application_create(
+        &self,
+        application: &ScimEntryApplicationPost,
+    ) -> Result<ScimEntryApplication, ClientError> {
+        self.perform_post_request("/scim/v1/Application", application)
+            .await
+    }
+}
diff --git a/server/lib/src/server/scim.rs b/server/lib/src/server/scim.rs
index 5f785777b..b48c84e3b 100644
--- a/server/lib/src/server/scim.rs
+++ b/server/lib/src/server/scim.rs
@@ -189,7 +189,51 @@ impl QueryServerWriteTransaction<'_> {
             entries: vec![entry],
         };
 
-        self.create(&create_event)
+        let mut changed_uuids = self.create(&create_event)?;
+
+        let target = if let Some(target) = changed_uuids.pop() {
+            if !changed_uuids.is_empty() {
+                // Too many results!
+                return Err(OperationError::UniqueConstraintViolation);
+            }
+
+            target
+        } else {
+            // No results!
+            return Err(OperationError::NoMatchingEntries);
+        };
+
+        // Now get the entry. We handle a lot of the errors here nicely,
+        // but if we got to this point, they really can't happen.
+        let filter_intent = filter!(f_and!([f_eq(Attribute::Uuid, PartialValue::Uuid(target))]));
+
+        let f_intent_valid = filter_intent
+            .validate(self.get_schema())
+            .map_err(OperationError::SchemaViolation)?;
+
+        let f_valid = f_intent_valid.clone().into_ignore_hidden();
+
+        let se = SearchEvent {
+            ident,
+            filter: f_valid,
+            filter_orig: f_intent_valid,
+            // Return all attributes
+            attrs: None,
+            effective_access_check: false,
+        };
+
+        let mut vs = self.search_ext(&se)?;
+        match vs.pop() {
+            Some(entry) if vs.is_empty() => entry.to_scim_kanidm(self),
+            _ => {
+                if vs.is_empty() {
+                    Err(OperationError::NoMatchingEntries)
+                } else {
+                    // Multiple entries matched, should not be possible!
+                    Err(OperationError::UniqueConstraintViolation)
+                }
+            }
+        }
     }
 
     pub fn scim_delete(&mut self, scim_delete: ScimDeleteEvent) -> Result<(), OperationError> {