This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-26196-keycloak-pojo-response
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7b461286f7c4989386d2e905c93c8ea311db483d
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Nov 3 00:12:33 2026 +0100

    CAMEL-26196: camel-keycloak - convert a pojoRequest body, fail a create or 
delete with a non-2xx status, and close its Response
    
    With pojoRequest=true, a body that was not the Keycloak representation of 
the
    operation did nothing: no call, no error, and the body was kept. The body is
    now converted (type converter, or a Map or JSON text), and fails with an
    InvalidPayloadException when it does not convert.
    
    The operations that give the JAX-RS Response of Keycloak (createUser,
    deleteUser, createGroup, createOrganization, ...) completed on a 409 or 404,
    and never closed the Response. A status other than 2xx now fails with a
    WebApplicationException, and the Response is closed (its status and Location
    can still be read). deleteOrganization, removeOrganizationMember and
    unlinkOrganizationIdentityProvider ignored their Response the same way.
    
    bulkCreateUsers and bulkUpdateUsers cast a List of Map to UserRepresentation
    and failed with a raw ClassCastException; each element is now converted.
    bulkCreateUsers and bulkDeleteUsers counted a 409 or 404 as a success.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../apache/camel/catalog/components/keycloak.json  |   4 +-
 .../camel/catalog/docs/keycloak-producer.adoc      |  26 +-
 .../apache/camel/component/keycloak/keycloak.json  |   4 +-
 .../src/main/docs/keycloak-producer.adoc           |  26 +-
 .../camel/component/keycloak/KeycloakEndpoint.java |  15 +-
 .../camel/component/keycloak/KeycloakProducer.java | 417 ++++++++++++---------
 ...KeycloakProducerPojoRequestAndResponseTest.java | 344 +++++++++++++++++
 .../component/keycloak/KeycloakProducerTest.java   |  10 +
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |  15 +
 9 files changed, 672 insertions(+), 189 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
index 3c9bd12bf19d..d6844636797c 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
@@ -129,8 +129,8 @@
   },
   "bodyTypes": {
     "consumerOut": { "carriers": [ "pojo" ], "javaType": 
"org.keycloak.representations.idm.EventRepresentation", "byOption": [ { 
"option": "eventType", "value": "admin-events", "carriers": [ "pojo" ], 
"javaType": "org.keycloak.representations.idm.AdminEventRepresentation" } ], 
"description": "One message per event: the EventRepresentation of a user event 
such as a login, or the AdminEventRepresentation with eventType=admin-events. 
The CamelKeycloakEventType header says event or admin-event" },
-    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": 
"pojoRequest", "value": "true", "carriers": [ "pojo" ] } ], "description": 
"Mostly not read: the operations take their input from headers, such as 
CamelKeycloakRealmName and CamelKeycloakUserId. With pojoRequest=true the 
create and update operations take the Keycloak representation, such as a 
UserRepresentation for createUser; a body of another type does nothing and 
keeps the body. The bulk operations take a List when t [...]
-    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"operation", "value": "createRealm", "carriers": [ "text" ], "javaType": 
"java.lang.String" }, { "option": "operation", "value": "deleteRealm", 
"carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": 
"operation", "value": "getRealm", "carriers": [ "pojo" ], "javaType": 
"org.keycloak.representations.idm.RealmRepresentation" }, { "option": 
"operation", "value": "updateRealm", "carriers": [ "text" ], "ja [...]
+    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": 
"pojoRequest", "value": "true", "carriers": [ "pojo" ] } ], "description": 
"Mostly not read: the operations take their input from headers, such as 
CamelKeycloakRealmName and CamelKeycloakUserId. With pojoRequest=true the 
create and update operations take the Keycloak representation, such as a 
UserRepresentation for createUser, or a Map or JSON text of it; a body that 
does not convert fails. The bulk operations take a Li [...]
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"operation", "value": "createRealm", "carriers": [ "text" ], "javaType": 
"java.lang.String" }, { "option": "operation", "value": "deleteRealm", 
"carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": 
"operation", "value": "getRealm", "carriers": [ "pojo" ], "javaType": 
"org.keycloak.representations.idm.RealmRepresentation" }, { "option": 
"operation", "value": "updateRealm", "carriers": [ "text" ], "ja [...]
   },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.keycloak.KeycloakConfiguration", 
"configurationField": "configuration", "description": "Logical name" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-producer.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-producer.adoc
index 320d98815f57..980b9e7bf553 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-producer.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/keycloak-producer.adoc
@@ -132,6 +132,29 @@ All producer operations follow the same pattern: set the 
operation name in the U
 template.sendBodyAndHeaders("keycloak:admin?operation=<operationName>", null, 
headers);
 ----
 
+=== Representation bodies
+
+With `pojoRequest=true`, the create and update operations take the Keycloak 
representation as the body, such as a
+`UserRepresentation` for `createUser` and `updateUser`. A body of another type 
is converted: a `Map` (such as
+unmarshalled JSON) or JSON text is mapped to the representation. A body that 
does not convert fails the exchange
+with an `InvalidPayloadException`.
+
+The elements of the `List` of `bulkCreateUsers` and `bulkUpdateUsers` are 
converted the same way; an element that
+does not convert fails the exchange before any user is created or updated.
+
+=== Results of create and delete operations
+
+`createUser`, `deleteUser`, `createGroup`, `createClient`, 
`createClientScope`, `createIdentityProvider`,
+`createResource`, `createResourcePolicy`, `createResourcePermission`, 
`createOrganization`, `updateOrganization`,
+`addOrganizationMember` and `linkOrganizationIdentityProvider` give the JAX-RS 
`Response` of Keycloak as the body.
+The Response is closed, but its status and headers can still be read, such as 
the `Location` header with the URL
+(ending with the id) of the created resource.
+
+When Keycloak answers with a status other than 2xx, such as 409 (already 
exists) or 404 (not found), the exchange
+fails with a `jakarta.ws.rs.WebApplicationException`, whose `getResponse()` 
gives the status. The same goes for
+`deleteOrganization`, `removeOrganizationMember` and 
`unlinkOrganizationIdentityProvider`. The bulk operations
+record such a status as a failed item.
+
 == User Operations
 
 [tabs]
@@ -672,7 +695,8 @@ All bulk operations return a consistent response format:
     {
       "username": "user2",
       "status": "failed",
-      "error": "User already exists"
+      "statusCode": 409,
+      "error": "Keycloak createUser failed with status 409: 
{\"errorMessage\":\"User exists with same username\"}"
     }
   ]
 }
diff --git 
a/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
 
b/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
index 3c9bd12bf19d..d6844636797c 100644
--- 
a/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
+++ 
b/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
@@ -129,8 +129,8 @@
   },
   "bodyTypes": {
     "consumerOut": { "carriers": [ "pojo" ], "javaType": 
"org.keycloak.representations.idm.EventRepresentation", "byOption": [ { 
"option": "eventType", "value": "admin-events", "carriers": [ "pojo" ], 
"javaType": "org.keycloak.representations.idm.AdminEventRepresentation" } ], 
"description": "One message per event: the EventRepresentation of a user event 
such as a login, or the AdminEventRepresentation with eventType=admin-events. 
The CamelKeycloakEventType header says event or admin-event" },
-    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": 
"pojoRequest", "value": "true", "carriers": [ "pojo" ] } ], "description": 
"Mostly not read: the operations take their input from headers, such as 
CamelKeycloakRealmName and CamelKeycloakUserId. With pojoRequest=true the 
create and update operations take the Keycloak representation, such as a 
UserRepresentation for createUser; a body of another type does nothing and 
keeps the body. The bulk operations take a List when t [...]
-    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"operation", "value": "createRealm", "carriers": [ "text" ], "javaType": 
"java.lang.String" }, { "option": "operation", "value": "deleteRealm", 
"carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": 
"operation", "value": "getRealm", "carriers": [ "pojo" ], "javaType": 
"org.keycloak.representations.idm.RealmRepresentation" }, { "option": 
"operation", "value": "updateRealm", "carriers": [ "text" ], "ja [...]
+    "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": 
"pojoRequest", "value": "true", "carriers": [ "pojo" ] } ], "description": 
"Mostly not read: the operations take their input from headers, such as 
CamelKeycloakRealmName and CamelKeycloakUserId. With pojoRequest=true the 
create and update operations take the Keycloak representation, such as a 
UserRepresentation for createUser, or a Map or JSON text of it; a body that 
does not convert fails. The bulk operations take a Li [...]
+    "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": 
"operation", "value": "createRealm", "carriers": [ "text" ], "javaType": 
"java.lang.String" }, { "option": "operation", "value": "deleteRealm", 
"carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": 
"operation", "value": "getRealm", "carriers": [ "pojo" ], "javaType": 
"org.keycloak.representations.idm.RealmRepresentation" }, { "option": 
"operation", "value": "updateRealm", "carriers": [ "text" ], "ja [...]
   },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.keycloak.KeycloakConfiguration", 
"configurationField": "configuration", "description": "Logical name" },
diff --git a/components/camel-keycloak/src/main/docs/keycloak-producer.adoc 
b/components/camel-keycloak/src/main/docs/keycloak-producer.adoc
index 320d98815f57..980b9e7bf553 100644
--- a/components/camel-keycloak/src/main/docs/keycloak-producer.adoc
+++ b/components/camel-keycloak/src/main/docs/keycloak-producer.adoc
@@ -132,6 +132,29 @@ All producer operations follow the same pattern: set the 
operation name in the U
 template.sendBodyAndHeaders("keycloak:admin?operation=<operationName>", null, 
headers);
 ----
 
+=== Representation bodies
+
+With `pojoRequest=true`, the create and update operations take the Keycloak 
representation as the body, such as a
+`UserRepresentation` for `createUser` and `updateUser`. A body of another type 
is converted: a `Map` (such as
+unmarshalled JSON) or JSON text is mapped to the representation. A body that 
does not convert fails the exchange
+with an `InvalidPayloadException`.
+
+The elements of the `List` of `bulkCreateUsers` and `bulkUpdateUsers` are 
converted the same way; an element that
+does not convert fails the exchange before any user is created or updated.
+
+=== Results of create and delete operations
+
+`createUser`, `deleteUser`, `createGroup`, `createClient`, 
`createClientScope`, `createIdentityProvider`,
+`createResource`, `createResourcePolicy`, `createResourcePermission`, 
`createOrganization`, `updateOrganization`,
+`addOrganizationMember` and `linkOrganizationIdentityProvider` give the JAX-RS 
`Response` of Keycloak as the body.
+The Response is closed, but its status and headers can still be read, such as 
the `Location` header with the URL
+(ending with the id) of the created resource.
+
+When Keycloak answers with a status other than 2xx, such as 409 (already 
exists) or 404 (not found), the exchange
+fails with a `jakarta.ws.rs.WebApplicationException`, whose `getResponse()` 
gives the status. The same goes for
+`deleteOrganization`, `removeOrganizationMember` and 
`unlinkOrganizationIdentityProvider`. The bulk operations
+record such a status as a failed item.
+
 == User Operations
 
 [tabs]
@@ -672,7 +695,8 @@ All bulk operations return a consistent response format:
     {
       "username": "user2",
       "status": "failed",
-      "error": "User already exists"
+      "statusCode": 409,
+      "error": "Keycloak createUser failed with status 409: 
{\"errorMessage\":\"User exists with same username\"}"
     }
   ]
 }
diff --git 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java
 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java
index a85258706031..0cc36f10b725 100644
--- 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java
+++ 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakEndpoint.java
@@ -50,10 +50,11 @@ import org.keycloak.admin.client.KeycloakBuilder;
                                   description = "Mostly not read: the 
operations take their input from headers, such as"
                                                 + " CamelKeycloakRealmName and 
CamelKeycloakUserId. With pojoRequest=true the"
                                                 + " create and update 
operations take the Keycloak representation, such as a"
-                                                + " UserRepresentation for 
createUser; a body of another type does nothing"
-                                                + " and keeps the body. The 
bulk operations take a List when"
-                                                + " the header is not set: of 
UserRepresentation for bulkCreateUsers and"
-                                                + " bulkUpdateUsers, of String 
ids or role names for the others."
+                                                + " UserRepresentation for 
createUser, or a Map or JSON text of it; a body"
+                                                + " that does not convert 
fails. The bulk operations take a List when"
+                                                + " the header is not set: of 
UserRepresentation (or a Map or JSON text of"
+                                                + " it) for bulkCreateUsers 
and bulkUpdateUsers, of String ids or role names"
+                                                + " for the others."
                                                 + " introspectToken, 
revokeAccessToken and revokeRefreshToken take the token"
                                                 + " as text when the 
CamelKeycloakToken header is not set"),
            producerOut = @BodyType(value = Carrier.UNKNOWN,
@@ -299,8 +300,10 @@ import org.keycloak.admin.client.KeycloakBuilder;
                                    description = "Depends on the operation, 
which the CamelKeycloakOperation header can set:"
                                                  + " get gives the Keycloak 
representation, such as a UserRepresentation, and"
                                                  + " list and search a List of 
them. Most create operations, deleteUser and"
-                                                 + " some organization 
operations give the JAX-RS Response, whose status says"
-                                                 + " whether it worked (a 409 
or 404 is no error); the others"
+                                                 + " some organization 
operations give the closed JAX-RS Response, whose"
+                                                 + " status and Location 
header (the URL of the created resource) can be"
+                                                 + " read; a status other than 
2xx fails with a WebApplicationException. The"
+                                                 + " others give"
                                                  + " a confirmation text such 
as Realm deleted successfully. The bulk"
                                                  + " operations give a Map 
with total, success, failed and results"))
 public class KeycloakEndpoint extends ScheduledPollEndpoint implements 
EndpointServiceLocation {
diff --git 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
index 0a9913dc2cbb..9a9c5f5cea29 100644
--- 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
+++ 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.component.keycloak;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Base64;
@@ -23,6 +25,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Response;
 
 import org.apache.camel.Endpoint;
@@ -63,6 +66,7 @@ import 
org.keycloak.representations.idm.authorization.Permission;
 import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import 
org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.util.JsonSerialization;
 
 /**
  * A Producer which sends messages to Keycloak Admin API
@@ -442,14 +446,107 @@ public class KeycloakProducer extends DefaultProducer {
         return (KeycloakEndpoint) super.getEndpoint();
     }
 
+    /**
+     * The body of a pojoRequest operation as the given Keycloak 
representation. Another type is converted: by a type
+     * converter, or from a Map (such as unmarshalled JSON) or JSON text. A 
body that does not convert fails.
+     */
+    private static <T> T getPojoRequest(Exchange exchange, Class<T> type) 
throws InvalidPayloadException {
+        Message in = exchange.getIn();
+        Object body = in.getMandatoryBody();
+        T answer;
+        try {
+            answer = toRepresentation(exchange, body, type);
+        } catch (IOException | IllegalArgumentException e) {
+            throw new InvalidPayloadException(exchange, type, in, e);
+        }
+        if (answer == null) {
+            throw new InvalidPayloadException(exchange, type, in);
+        }
+        return answer;
+    }
+
+    /**
+     * Converts each element of a List body or header to the given Keycloak 
representation, the same way as
+     * {@link #getPojoRequest(Exchange, Class)}. An element that does not 
convert fails before any call to Keycloak.
+     */
+    private static <T> List<T> toRepresentations(Exchange exchange, List<?> 
list, Class<T> type) {
+        List<T> answer = new ArrayList<>(list.size());
+        for (int i = 0; i < list.size(); i++) {
+            Object element = list.get(i);
+            T value = null;
+            if (element != null) {
+                try {
+                    value = toRepresentation(exchange, element, type);
+                } catch (IOException | IllegalArgumentException e) {
+                    throw new IllegalArgumentException(
+                            "Element " + i + " of the list cannot be converted 
to " + type.getSimpleName() + ": "
+                                                       + e.getMessage(),
+                            e);
+                }
+            }
+            if (value == null) {
+                throw new IllegalArgumentException(
+                        "Element " + i + " of the list must be a " + 
type.getSimpleName() + ", a Map or JSON text, but was: "
+                                                   + (element != null ? 
element.getClass().getName() : "null"));
+            }
+            answer.add(value);
+        }
+        return answer;
+    }
+
+    private static <T> T toRepresentation(Exchange exchange, Object value, 
Class<T> type) throws IOException {
+        if (type.isInstance(value)) {
+            return type.cast(value);
+        }
+        T answer = exchange.getContext().getTypeConverter().tryConvertTo(type, 
exchange, value);
+        if (answer != null) {
+            return answer;
+        }
+        if (value instanceof Map) {
+            return JsonSerialization.mapper.convertValue(value, type);
+        }
+        if (value instanceof CharSequence || value instanceof byte[] || value 
instanceof InputStream) {
+            String json = 
exchange.getContext().getTypeConverter().tryConvertTo(String.class, exchange, 
value);
+            if (json != null) {
+                return JsonSerialization.readValue(json, type);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Fails on a non-2xx status of a Response that Keycloak returned, and 
closes it. The closed Response is returned:
+     * its status and headers, such as the Location of a created resource, can 
still be read.
+     */
+    private static Response checkResponse(Response response, String operation) 
{
+        try {
+            int status = response.getStatus();
+            if (status < 200 || status >= 300) {
+                String error = null;
+                try {
+                    if (response.hasEntity()) {
+                        error = response.readEntity(String.class);
+                    }
+                } catch (Exception e) {
+                    // ignore, the status is enough
+                }
+                throw new WebApplicationException(
+                        "Keycloak " + operation + " failed with status " + 
status
+                                                  + 
(ObjectHelper.isNotEmpty(error) ? ": " + error : ""),
+                        response);
+            }
+        } finally {
+            response.close();
+        }
+        return response;
+    }
+
     private void createRealm(Keycloak keycloakClient, Exchange exchange) 
throws InvalidPayloadException {
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RealmRepresentation rr) {
-                keycloakClient.realms().create(rr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Realm created successfully");
-            }
+            RealmRepresentation rr = getPojoRequest(exchange, 
RealmRepresentation.class);
+            keycloakClient.realms().create(rr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Realm created successfully");
         } else {
             RealmRepresentation realm = new RealmRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.REALM_NAME)))
 {
@@ -494,12 +591,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RealmRepresentation rr) {
-                keycloakClient.realm(realmName).update(rr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Realm updated successfully");
-            }
+            RealmRepresentation rr = getPojoRequest(exchange, 
RealmRepresentation.class);
+            keycloakClient.realm(realmName).update(rr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Realm updated successfully");
         } else {
             throw new IllegalArgumentException("Update realm requires POJO 
request with RealmRepresentation");
         }
@@ -512,12 +607,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof UserRepresentation ur) {
-                Response response = 
keycloakClient.realm(realmName).users().create(ur);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            UserRepresentation ur = getPojoRequest(exchange, 
UserRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).users().create(ur);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createUser"));
         } else {
             UserRepresentation user = new UserRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.USERNAME)))
 {
@@ -539,7 +632,7 @@ public class KeycloakProducer extends DefaultProducer {
             }
             Response response = 
keycloakClient.realm(realmName).users().create(user);
             Message message = getMessageForResponse(exchange);
-            message.setBody(response);
+            message.setBody(checkResponse(response, "createUser"));
         }
     }
 
@@ -556,7 +649,7 @@ public class KeycloakProducer extends DefaultProducer {
 
         Response response = 
keycloakClient.realm(realmName).users().delete(userId);
         Message message = getMessageForResponse(exchange);
-        message.setBody(response);
+        message.setBody(checkResponse(response, "deleteUser"));
     }
 
     private void getUser(Keycloak keycloakClient, Exchange exchange) {
@@ -587,12 +680,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof UserRepresentation ur) {
-                keycloakClient.realm(realmName).users().get(userId).update(ur);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("User updated successfully");
-            }
+            UserRepresentation ur = getPojoRequest(exchange, 
UserRepresentation.class);
+            keycloakClient.realm(realmName).users().get(userId).update(ur);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("User updated successfully");
         } else {
             throw new IllegalArgumentException("Update user requires POJO 
request with UserRepresentation");
         }
@@ -616,12 +707,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RoleRepresentation rr) {
-                keycloakClient.realm(realmName).roles().create(rr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Role created successfully");
-            }
+            RoleRepresentation rr = getPojoRequest(exchange, 
RoleRepresentation.class);
+            keycloakClient.realm(realmName).roles().create(rr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Role created successfully");
         } else {
             RoleRepresentation role = new RoleRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME)))
 {
@@ -684,12 +773,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RoleRepresentation rr) {
-                
keycloakClient.realm(realmName).roles().get(roleName).update(rr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Role updated successfully");
-            }
+            RoleRepresentation rr = getPojoRequest(exchange, 
RoleRepresentation.class);
+            keycloakClient.realm(realmName).roles().get(roleName).update(rr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Role updated successfully");
         } else {
             throw new IllegalArgumentException("Update role requires POJO 
request with RoleRepresentation");
         }
@@ -757,12 +844,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof GroupRepresentation gr) {
-                Response response = 
keycloakClient.realm(realmName).groups().add(gr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            GroupRepresentation gr = getPojoRequest(exchange, 
GroupRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).groups().add(gr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createGroup"));
         } else {
             GroupRepresentation group = new GroupRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.GROUP_NAME)))
 {
@@ -773,7 +858,7 @@ public class KeycloakProducer extends DefaultProducer {
             }
             Response response = 
keycloakClient.realm(realmName).groups().add(group);
             Message message = getMessageForResponse(exchange);
-            message.setBody(response);
+            message.setBody(checkResponse(response, "createGroup"));
         }
     }
 
@@ -821,12 +906,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof GroupRepresentation gr) {
-                
keycloakClient.realm(realmName).groups().group(groupId).update(gr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Group updated successfully");
-            }
+            GroupRepresentation gr = getPojoRequest(exchange, 
GroupRepresentation.class);
+            keycloakClient.realm(realmName).groups().group(groupId).update(gr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Group updated successfully");
         } else {
             throw new IllegalArgumentException("Update group requires POJO 
request with GroupRepresentation");
         }
@@ -908,12 +991,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ClientRepresentation cr) {
-                Response response = 
keycloakClient.realm(realmName).clients().create(cr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            ClientRepresentation cr = getPojoRequest(exchange, 
ClientRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).clients().create(cr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createClient"));
         } else {
             ClientRepresentation client = new ClientRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.CLIENT_ID)))
 {
@@ -925,7 +1006,7 @@ public class KeycloakProducer extends DefaultProducer {
             }
             Response response = 
keycloakClient.realm(realmName).clients().create(client);
             Message message = getMessageForResponse(exchange);
-            message.setBody(response);
+            message.setBody(checkResponse(response, "createClient"));
         }
     }
 
@@ -973,12 +1054,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ClientRepresentation cr) {
-                
keycloakClient.realm(realmName).clients().get(clientUuid).update(cr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Client updated successfully");
-            }
+            ClientRepresentation cr = getPojoRequest(exchange, 
ClientRepresentation.class);
+            
keycloakClient.realm(realmName).clients().get(clientUuid).update(cr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Client updated successfully");
         } else {
             throw new IllegalArgumentException("Update client requires POJO 
request with ClientRepresentation");
         }
@@ -1052,12 +1131,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RoleRepresentation rr) {
-                
keycloakClient.realm(realmName).clients().get(clientUuid).roles().create(rr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Client role created successfully");
-            }
+            RoleRepresentation rr = getPojoRequest(exchange, 
RoleRepresentation.class);
+            
keycloakClient.realm(realmName).clients().get(clientUuid).roles().create(rr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Client role created successfully");
         } else {
             RoleRepresentation role = new RoleRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.ROLE_NAME)))
 {
@@ -1136,13 +1213,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RoleRepresentation rr) {
-                
keycloakClient.realm(realmName).clients().get(clientUuid).roles().get(roleName)
-                        .update(rr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Client role updated successfully");
-            }
+            RoleRepresentation rr = getPojoRequest(exchange, 
RoleRepresentation.class);
+            
keycloakClient.realm(realmName).clients().get(clientUuid).roles().get(roleName)
+                    .update(rr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Client role updated successfully");
         } else {
             throw new IllegalArgumentException("Update client role requires 
POJO request with RoleRepresentation");
         }
@@ -1407,12 +1482,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ClientScopeRepresentation csr) {
-                Response response = 
keycloakClient.realm(realmName).clientScopes().create(csr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            ClientScopeRepresentation csr = getPojoRequest(exchange, 
ClientScopeRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).clientScopes().create(csr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createClientScope"));
         } else {
             ClientScopeRepresentation clientScope = new 
ClientScopeRepresentation();
             if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(KeycloakConstants.CLIENT_SCOPE_NAME)))
 {
@@ -1423,7 +1496,7 @@ public class KeycloakProducer extends DefaultProducer {
             }
             Response response = 
keycloakClient.realm(realmName).clientScopes().create(clientScope);
             Message message = getMessageForResponse(exchange);
-            message.setBody(response);
+            message.setBody(checkResponse(response, "createClientScope"));
         }
     }
 
@@ -1472,12 +1545,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ClientScopeRepresentation csr) {
-                
keycloakClient.realm(realmName).clientScopes().get(clientScopeId).update(csr);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Client scope updated successfully");
-            }
+            ClientScopeRepresentation csr = getPojoRequest(exchange, 
ClientScopeRepresentation.class);
+            
keycloakClient.realm(realmName).clientScopes().get(clientScopeId).update(csr);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Client scope updated successfully");
         } else {
             throw new IllegalArgumentException("Update client scope requires 
POJO request with ClientScopeRepresentation");
         }
@@ -1502,13 +1573,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof IdentityProviderRepresentation 
idpRepresentation) {
-                Response response
-                        = 
keycloakClient.realm(realmName).identityProviders().create(idpRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            IdentityProviderRepresentation idpRepresentation = 
getPojoRequest(exchange, IdentityProviderRepresentation.class);
+            Response response
+                    = 
keycloakClient.realm(realmName).identityProviders().create(idpRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createIdentityProvider"));
         } else {
             throw new IllegalArgumentException(
                     "Create identity provider requires POJO request with 
IdentityProviderRepresentation");
@@ -1560,13 +1629,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof IdentityProviderRepresentation 
idpRepresentation) {
-                
keycloakClient.realm(realmName).identityProviders().get(idpAlias)
-                        .update(idpRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Identity provider updated successfully");
-            }
+            IdentityProviderRepresentation idpRepresentation = 
getPojoRequest(exchange, IdentityProviderRepresentation.class);
+            keycloakClient.realm(realmName).identityProviders().get(idpAlias)
+                    .update(idpRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Identity provider updated successfully");
         } else {
             throw new IllegalArgumentException(
                     "Update identity provider requires POJO request with 
IdentityProviderRepresentation");
@@ -1597,13 +1664,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ResourceRepresentation 
resourceRepresentation) {
-                Response response = 
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().resources()
-                        .create(resourceRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            ResourceRepresentation resourceRepresentation = 
getPojoRequest(exchange, ResourceRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().resources()
+                    .create(resourceRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createResource"));
         } else {
             throw new IllegalArgumentException("Create resource requires POJO 
request with ResourceRepresentation");
         }
@@ -1670,13 +1735,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ResourceRepresentation 
resourceRepresentation) {
-                
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().resources().resource(resourceId)
-                        .update(resourceRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Resource updated successfully");
-            }
+            ResourceRepresentation resourceRepresentation = 
getPojoRequest(exchange, ResourceRepresentation.class);
+            
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().resources().resource(resourceId)
+                    .update(resourceRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Resource updated successfully");
         } else {
             throw new IllegalArgumentException("Update resource requires POJO 
request with ResourceRepresentation");
         }
@@ -1711,13 +1774,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof PolicyRepresentation policyRepresentation) {
-                Response response = 
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().policies()
-                        .create(policyRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            PolicyRepresentation policyRepresentation = 
getPojoRequest(exchange, PolicyRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().policies()
+                    .create(policyRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createResourcePolicy"));
         } else {
             throw new IllegalArgumentException("Create policy requires POJO 
request with PolicyRepresentation");
         }
@@ -1784,13 +1845,11 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof PolicyRepresentation policyRepresentation) {
-                
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().policies().policy(policyId)
-                        .update(policyRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Policy updated successfully");
-            }
+            PolicyRepresentation policyRepresentation = 
getPojoRequest(exchange, PolicyRepresentation.class);
+            
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().policies().policy(policyId)
+                    .update(policyRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Policy updated successfully");
         } else {
             throw new IllegalArgumentException("Update policy requires POJO 
request with PolicyRepresentation");
         }
@@ -1825,13 +1884,12 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ResourcePermissionRepresentation 
permissionRepresentation) {
-                Response response = 
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().permissions()
-                        .resource().create(permissionRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            ResourcePermissionRepresentation permissionRepresentation
+                    = getPojoRequest(exchange, 
ResourcePermissionRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().permissions()
+                    .resource().create(permissionRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, 
"createResourcePermission"));
         } else {
             throw new IllegalArgumentException("Create permission requires 
POJO request with ResourcePermissionRepresentation");
         }
@@ -1900,14 +1958,12 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof PolicyRepresentation policyRepresentation) {
-                // Use policy endpoint for permissions
-                
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().policies().policy(permissionId)
-                        .update(policyRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody("Permission updated successfully");
-            }
+            PolicyRepresentation policyRepresentation = 
getPojoRequest(exchange, PolicyRepresentation.class);
+            // Use policy endpoint for permissions
+            
keycloakClient.realm(realmName).clients().get(clientUuid).authorization().policies().policy(permissionId)
+                    .update(policyRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody("Permission updated successfully");
         } else {
             throw new IllegalArgumentException("Update permission requires 
POJO request with PolicyRepresentation");
         }
@@ -2330,16 +2386,18 @@ public class KeycloakProducer extends DefaultProducer {
             throw new IllegalArgumentException(MISSING_REALM_NAME);
         }
 
-        List<UserRepresentation> users = 
exchange.getIn().getHeader(KeycloakConstants.USERS, List.class);
-        if (users == null || users.isEmpty()) {
+        List<?> list = exchange.getIn().getHeader(KeycloakConstants.USERS, 
List.class);
+        if (list == null || list.isEmpty()) {
             // Try to get from body
             Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof List) {
-                users = CastUtils.cast((List<?>) payload);
+            if (payload instanceof List<?> l) {
+                list = l;
             } else {
                 throw new IllegalArgumentException("Users list must be 
provided via header or body");
             }
         }
+        // the elements can be Maps (such as unmarshalled JSON) or JSON text 
as well
+        List<UserRepresentation> users = toRepresentations(exchange, list, 
UserRepresentation.class);
 
         boolean continueOnError
                 = 
exchange.getIn().getHeader(KeycloakConstants.CONTINUE_ON_ERROR, Boolean.FALSE, 
Boolean.class);
@@ -2350,13 +2408,16 @@ public class KeycloakProducer extends DefaultProducer {
         for (UserRepresentation user : users) {
             Map<String, Object> result = new HashMap<>();
             result.put("username", user.getUsername());
-            try (Response response = 
keycloakClient.realm(realmName).users().create(user)) {
+            try {
+                Response response = 
checkResponse(keycloakClient.realm(realmName).users().create(user), 
"createUser");
                 result.put("status", "success");
                 result.put("statusCode", response.getStatus());
                 successCount++;
-                response.close();
             } catch (Exception e) {
                 result.put("status", "failed");
+                if (e instanceof WebApplicationException wae) {
+                    result.put("statusCode", wae.getResponse().getStatus());
+                }
                 result.put("error", e.getMessage());
                 failureCount++;
                 if (!continueOnError) {
@@ -2417,13 +2478,15 @@ public class KeycloakProducer extends DefaultProducer {
             Map<String, Object> result = new HashMap<>();
             result.put("userId", userId);
             try {
-                Response response = 
keycloakClient.realm(realmName).users().delete(userId);
+                Response response = 
checkResponse(keycloakClient.realm(realmName).users().delete(userId), 
"deleteUser");
                 result.put("status", "success");
                 result.put("statusCode", response.getStatus());
                 successCount++;
-                response.close();
             } catch (Exception e) {
                 result.put("status", "failed");
+                if (e instanceof WebApplicationException wae) {
+                    result.put("statusCode", wae.getResponse().getStatus());
+                }
                 result.put("error", e.getMessage());
                 failureCount++;
                 if (!continueOnError) {
@@ -2597,16 +2660,18 @@ public class KeycloakProducer extends DefaultProducer {
             throw new IllegalArgumentException(MISSING_REALM_NAME);
         }
 
-        List<UserRepresentation> users = 
exchange.getIn().getHeader(KeycloakConstants.USERS, List.class);
-        if (users == null || users.isEmpty()) {
+        List<?> list = exchange.getIn().getHeader(KeycloakConstants.USERS, 
List.class);
+        if (list == null || list.isEmpty()) {
             // Try to get from body
             Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof List) {
-                users = CastUtils.cast((List<?>) payload);
+            if (payload instanceof List<?> l) {
+                list = l;
             } else {
                 throw new IllegalArgumentException("Users list must be 
provided via header or body");
             }
         }
+        // the elements can be Maps (such as unmarshalled JSON) or JSON text 
as well
+        List<UserRepresentation> users = toRepresentations(exchange, list, 
UserRepresentation.class);
 
         boolean continueOnError
                 = 
exchange.getIn().getHeader(KeycloakConstants.CONTINUE_ON_ERROR, Boolean.FALSE, 
Boolean.class);
@@ -2654,12 +2719,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof OrganizationRepresentation 
orgRepresentation) {
-                Response response = 
keycloakClient.realm(realmName).organizations().create(orgRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            OrganizationRepresentation orgRepresentation = 
getPojoRequest(exchange, OrganizationRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).organizations().create(orgRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "createOrganization"));
         } else {
             String orgName = 
exchange.getIn().getHeader(KeycloakConstants.ORGANIZATION_NAME, String.class);
             if (ObjectHelper.isEmpty(orgName)) {
@@ -2690,7 +2753,7 @@ public class KeycloakProducer extends DefaultProducer {
 
             Response response = 
keycloakClient.realm(realmName).organizations().create(org);
             Message message = getMessageForResponse(exchange);
-            message.setBody(response);
+            message.setBody(checkResponse(response, "createOrganization"));
         }
     }
 
@@ -2706,12 +2769,10 @@ public class KeycloakProducer extends DefaultProducer {
         }
 
         if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof OrganizationRepresentation 
orgRepresentation) {
-                Response response = 
keycloakClient.realm(realmName).organizations().get(orgId).update(orgRepresentation);
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
+            OrganizationRepresentation orgRepresentation = 
getPojoRequest(exchange, OrganizationRepresentation.class);
+            Response response = 
keycloakClient.realm(realmName).organizations().get(orgId).update(orgRepresentation);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(checkResponse(response, "updateOrganization"));
         } else {
             throw new IllegalArgumentException("Update organization requires 
POJO request with OrganizationRepresentation");
         }
@@ -2728,7 +2789,7 @@ public class KeycloakProducer extends DefaultProducer {
             throw new IllegalArgumentException(MISSING_ORGANIZATION_ID);
         }
 
-        keycloakClient.realm(realmName).organizations().get(orgId).delete();
+        
checkResponse(keycloakClient.realm(realmName).organizations().get(orgId).delete(),
 "deleteOrganization");
         Message message = getMessageForResponse(exchange);
         message.setBody("Organization deleted successfully");
     }
@@ -2811,7 +2872,7 @@ public class KeycloakProducer extends DefaultProducer {
 
         Response response = 
keycloakClient.realm(realmName).organizations().get(orgId).members().addMember(userId);
         Message message = getMessageForResponse(exchange);
-        message.setBody(response);
+        message.setBody(checkResponse(response, "addOrganizationMember"));
     }
 
     private void removeOrganizationMember(Keycloak keycloakClient, Exchange 
exchange) {
@@ -2830,7 +2891,8 @@ public class KeycloakProducer extends DefaultProducer {
             throw new IllegalArgumentException(MISSING_ORGANIZATION_MEMBER_ID);
         }
 
-        
keycloakClient.realm(realmName).organizations().get(orgId).members().member(userId).delete();
+        
checkResponse(keycloakClient.realm(realmName).organizations().get(orgId).members().member(userId).delete(),
+                "removeOrganizationMember");
         Message message = getMessageForResponse(exchange);
         message.setBody("Organization member removed successfully");
     }
@@ -2878,7 +2940,7 @@ public class KeycloakProducer extends DefaultProducer {
         Response response
                 = 
keycloakClient.realm(realmName).organizations().get(orgId).identityProviders().addIdentityProvider(idpAlias);
         Message message = getMessageForResponse(exchange);
-        message.setBody(response);
+        message.setBody(checkResponse(response, 
"linkOrganizationIdentityProvider"));
     }
 
     private void unlinkOrganizationIdentityProvider(Keycloak keycloakClient, 
Exchange exchange) {
@@ -2897,7 +2959,8 @@ public class KeycloakProducer extends DefaultProducer {
             throw new IllegalArgumentException(MISSING_ORGANIZATION_IDP_ALIAS);
         }
 
-        
keycloakClient.realm(realmName).organizations().get(orgId).identityProviders().get(idpAlias).delete();
+        
checkResponse(keycloakClient.realm(realmName).organizations().get(orgId).identityProviders().get(idpAlias).delete(),
+                "unlinkOrganizationIdentityProvider");
         Message message = getMessageForResponse(exchange);
         message.setBody("Organization identity provider unlinked 
successfully");
     }
diff --git 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerPojoRequestAndResponseTest.java
 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerPojoRequestAndResponseTest.java
new file mode 100644
index 000000000000..2c7445518e48
--- /dev/null
+++ 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerPojoRequestAndResponseTest.java
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.keycloak;
+
+import java.util.List;
+import java.util.Map;
+
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.GroupsResource;
+import org.keycloak.admin.client.resource.OrganizationResource;
+import org.keycloak.admin.client.resource.OrganizationsResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.admin.client.resource.UsersResource;
+import org.keycloak.representations.idm.GroupRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * A pojoRequest body of another type is converted or fails, and the Response 
of a create or delete is checked and
+ * closed.
+ */
+public class KeycloakProducerPojoRequestAndResponseTest extends 
CamelTestSupport {
+
+    @BindToRegistry("keycloakClient")
+    private Keycloak keycloakClient = Mockito.mock(Keycloak.class);
+
+    private RealmResource realmResource = Mockito.mock(RealmResource.class);
+    private UsersResource usersResource = Mockito.mock(UsersResource.class);
+    private UserResource userResource = Mockito.mock(UserResource.class);
+    private GroupsResource groupsResource = Mockito.mock(GroupsResource.class);
+    private OrganizationsResource organizationsResource = 
Mockito.mock(OrganizationsResource.class);
+    private OrganizationResource organizationResource = 
Mockito.mock(OrganizationResource.class);
+
+    @BeforeEach
+    void setupMocks() {
+        when(keycloakClient.realm(anyString())).thenReturn(realmResource);
+        when(realmResource.users()).thenReturn(usersResource);
+        when(usersResource.get(anyString())).thenReturn(userResource);
+        when(realmResource.groups()).thenReturn(groupsResource);
+        when(realmResource.organizations()).thenReturn(organizationsResource);
+        
when(organizationsResource.get(anyString())).thenReturn(organizationResource);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:createUserPojo")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=createUser&pojoRequest=true");
+                from("direct:updateUserPojo")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=updateUser&pojoRequest=true");
+                from("direct:createGroup")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=createGroup");
+                from("direct:deleteUser")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=deleteUser");
+                from("direct:deleteOrganization")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=deleteOrganization");
+                from("direct:bulkCreateUsers")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=bulkCreateUsers");
+                from("direct:bulkUpdateUsers")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=bulkUpdateUsers");
+                from("direct:bulkDeleteUsers")
+                        
.to("keycloak:test?keycloakClient=#keycloakClient&operation=bulkDeleteUsers");
+            }
+        };
+    }
+
+    private static Response response(int status) {
+        Response response = Mockito.mock(Response.class);
+        when(response.getStatus()).thenReturn(status);
+        return response;
+    }
+
+    @Test
+    public void testCreateUserPojoFromJsonText() {
+        Response created = response(201);
+        
when(usersResource.create(any(UserRepresentation.class))).thenReturn(created);
+
+        Exchange out = template.request("direct:createUserPojo", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            
e.getIn().setBody("{\"username\":\"alice\",\"email\":\"[email protected]\",\"enabled\":true}");
+        });
+
+        assertNull(out.getException());
+        ArgumentCaptor<UserRepresentation> captor = 
ArgumentCaptor.forClass(UserRepresentation.class);
+        verify(usersResource).create(captor.capture());
+        assertEquals("alice", captor.getValue().getUsername());
+        assertEquals("[email protected]", captor.getValue().getEmail());
+        assertSame(created, out.getMessage().getBody());
+        verify(created).close();
+    }
+
+    @Test
+    public void testUpdateUserPojoFromMap() {
+        Exchange out = template.request("direct:updateUserPojo", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.USER_ID, "user-1");
+            e.getIn().setBody(Map.of("firstName", "Alice", "lastName", 
"Smith"));
+        });
+
+        assertNull(out.getException());
+        ArgumentCaptor<UserRepresentation> captor = 
ArgumentCaptor.forClass(UserRepresentation.class);
+        verify(userResource).update(captor.capture());
+        assertEquals("Alice", captor.getValue().getFirstName());
+        assertEquals("Smith", captor.getValue().getLastName());
+        assertEquals("User updated successfully", out.getMessage().getBody());
+    }
+
+    @Test
+    public void testCreateUserPojoWrongBodyFails() {
+        Exchange out = template.request("direct:createUserPojo", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setBody(42);
+        });
+
+        InvalidPayloadException cause = 
assertInstanceOf(InvalidPayloadException.class, out.getException());
+        assertEquals(UserRepresentation.class, cause.getType());
+        verify(usersResource, never()).create(any(UserRepresentation.class));
+    }
+
+    @Test
+    public void testCreateUserPojoInvalidJsonFails() {
+        Exchange out = template.request("direct:createUserPojo", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setBody("not json");
+        });
+
+        InvalidPayloadException cause = 
assertInstanceOf(InvalidPayloadException.class, out.getException());
+        assertEquals(UserRepresentation.class, cause.getType());
+        assertNotNull(cause.getCause());
+        verify(usersResource, never()).create(any(UserRepresentation.class));
+    }
+
+    @Test
+    public void testCreateUserConflictFails() {
+        Response conflict = response(409);
+        when(conflict.hasEntity()).thenReturn(true);
+        
when(conflict.readEntity(String.class)).thenReturn("{\"errorMessage\":\"User 
exists with same username\"}");
+        
when(usersResource.create(any(UserRepresentation.class))).thenReturn(conflict);
+
+        Exchange out = template.request("direct:createUserPojo", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setBody(new UserRepresentation());
+        });
+
+        WebApplicationException cause = 
assertInstanceOf(WebApplicationException.class, out.getException());
+        assertEquals(409, cause.getResponse().getStatus());
+        assertTrue(cause.getMessage().contains("createUser failed with status 
409"), cause.getMessage());
+        assertTrue(cause.getMessage().contains("User exists with same 
username"), cause.getMessage());
+        verify(conflict).close();
+    }
+
+    @Test
+    public void testCreateGroupConflictFails() {
+        Response conflict = response(409);
+        
when(groupsResource.add(any(GroupRepresentation.class))).thenReturn(conflict);
+
+        Exchange out = template.request("direct:createGroup", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.GROUP_NAME, "admins");
+        });
+
+        WebApplicationException cause = 
assertInstanceOf(WebApplicationException.class, out.getException());
+        assertEquals(409, cause.getResponse().getStatus());
+        verify(conflict).close();
+    }
+
+    @Test
+    public void testDeleteUserNotFoundFails() {
+        Response notFound = response(404);
+        when(usersResource.delete("missing")).thenReturn(notFound);
+
+        Exchange out = template.request("direct:deleteUser", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.USER_ID, "missing");
+        });
+
+        WebApplicationException cause = 
assertInstanceOf(WebApplicationException.class, out.getException());
+        assertEquals(404, cause.getResponse().getStatus());
+        verify(notFound).close();
+    }
+
+    @Test
+    public void testDeleteUserClosesResponse() {
+        Response noContent = response(204);
+        when(usersResource.delete("user-1")).thenReturn(noContent);
+
+        Exchange out = template.request("direct:deleteUser", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.USER_ID, "user-1");
+        });
+
+        assertNull(out.getException());
+        assertSame(noContent, out.getMessage().getBody());
+        verify(noContent).close();
+    }
+
+    @Test
+    public void testDeleteOrganizationNotFoundFails() {
+        Response notFound = response(404);
+        when(organizationResource.delete()).thenReturn(notFound);
+
+        Exchange out = template.request("direct:deleteOrganization", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.ORGANIZATION_ID, "missing");
+        });
+
+        WebApplicationException cause = 
assertInstanceOf(WebApplicationException.class, out.getException());
+        assertEquals(404, cause.getResponse().getStatus());
+        verify(notFound).close();
+    }
+
+    @Test
+    public void testBulkCreateUsersFromListOfMap() {
+        Response created = response(201);
+        
when(usersResource.create(any(UserRepresentation.class))).thenReturn(created);
+
+        Exchange out = template.request("direct:bulkCreateUsers", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setBody(List.of(Map.of("username", "alice"), 
"{\"username\":\"bob\"}"));
+        });
+
+        assertNull(out.getException());
+        ArgumentCaptor<UserRepresentation> captor = 
ArgumentCaptor.forClass(UserRepresentation.class);
+        verify(usersResource, times(2)).create(captor.capture());
+        assertEquals("alice", captor.getAllValues().get(0).getUsername());
+        assertEquals("bob", captor.getAllValues().get(1).getUsername());
+        verify(created, times(2)).close();
+
+        Map<?, ?> summary = out.getMessage().getBody(Map.class);
+        assertEquals(2, summary.get("success"));
+        assertEquals(0, summary.get("failed"));
+    }
+
+    @Test
+    public void testBulkCreateUsersWrongElementFails() {
+        Exchange out = template.request("direct:bulkCreateUsers", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setBody(List.of(Map.of("username", "alice"), 42));
+        });
+
+        IllegalArgumentException cause = 
assertInstanceOf(IllegalArgumentException.class, out.getException());
+        assertTrue(cause.getMessage().contains("Element 1 of the list must be 
a UserRepresentation"), cause.getMessage());
+        verify(usersResource, never()).create(any(UserRepresentation.class));
+    }
+
+    @Test
+    public void testBulkCreateUsersConflictIsFailed() {
+        Response created = response(201);
+        Response conflict = response(409);
+        
when(usersResource.create(any(UserRepresentation.class))).thenReturn(created, 
conflict);
+
+        Exchange out = template.request("direct:bulkCreateUsers", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.CONTINUE_ON_ERROR, true);
+            e.getIn().setBody(List.of(Map.of("username", "alice"), 
Map.of("username", "bob")));
+        });
+
+        assertNull(out.getException());
+        Map<?, ?> summary = out.getMessage().getBody(Map.class);
+        assertEquals(1, summary.get("success"));
+        assertEquals(1, summary.get("failed"));
+        List<?> results = (List<?>) summary.get("results");
+        Map<?, ?> second = (Map<?, ?>) results.get(1);
+        assertEquals("failed", second.get("status"));
+        assertEquals(409, second.get("statusCode"));
+        verify(created).close();
+        verify(conflict).close();
+    }
+
+    @Test
+    public void testBulkUpdateUsersFromListOfMap() {
+        Exchange out = template.request("direct:bulkUpdateUsers", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setBody(List.of(Map.of("id", "user-1", "firstName", 
"Alice")));
+        });
+
+        assertNull(out.getException());
+        ArgumentCaptor<UserRepresentation> captor = 
ArgumentCaptor.forClass(UserRepresentation.class);
+        verify(userResource).update(captor.capture());
+        assertEquals("Alice", captor.getValue().getFirstName());
+    }
+
+    @Test
+    public void testBulkDeleteUsersNotFoundIsFailed() {
+        Response noContent = response(204);
+        Response notFound = response(404);
+        when(usersResource.delete("user-1")).thenReturn(noContent);
+        when(usersResource.delete("missing")).thenReturn(notFound);
+
+        Exchange out = template.request("direct:bulkDeleteUsers", e -> {
+            e.getIn().setHeader(KeycloakConstants.REALM_NAME, "testRealm");
+            e.getIn().setHeader(KeycloakConstants.CONTINUE_ON_ERROR, true);
+            e.getIn().setBody(List.of("user-1", "missing"));
+        });
+
+        assertNull(out.getException());
+        Map<?, ?> summary = out.getMessage().getBody(Map.class);
+        assertEquals(1, summary.get("success"));
+        assertEquals(1, summary.get("failed"));
+        verify(noContent).close();
+        verify(notFound).close();
+    }
+}
diff --git 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java
 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java
index f149a7e7fd94..aa547c25e3d6 100644
--- 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java
+++ 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerTest.java
@@ -25,6 +25,7 @@ import org.apache.camel.BindToRegistry;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.keycloak.admin.client.Keycloak;
 import org.keycloak.admin.client.resource.ClientsResource;
@@ -79,6 +80,12 @@ public class KeycloakProducerTest extends CamelTestSupport {
             = Mockito.mock(OrganizationIdentityProviderResource.class);
     private Response response = Mockito.mock(Response.class);
 
+    @BeforeEach
+    void stubCreatedResponse() {
+        // a failed status fails the exchange, so the shared Response is a 
success
+        when(response.getStatus()).thenReturn(201);
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
@@ -462,6 +469,7 @@ public class KeycloakProducerTest extends CamelTestSupport {
         when(keycloakClient.realm(anyString())).thenReturn(realmResource);
         when(realmResource.organizations()).thenReturn(organizationsResource);
         
when(organizationsResource.get(anyString())).thenReturn(organizationResource);
+        when(organizationResource.delete()).thenReturn(response);
 
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedMessageCount(1);
@@ -515,6 +523,7 @@ public class KeycloakProducerTest extends CamelTestSupport {
         
when(organizationsResource.get(anyString())).thenReturn(organizationResource);
         
when(organizationResource.members()).thenReturn(organizationMembersResource);
         
when(organizationMembersResource.member(anyString())).thenReturn(organizationMemberResource);
+        when(organizationMemberResource.delete()).thenReturn(response);
 
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedMessageCount(1);
@@ -571,6 +580,7 @@ public class KeycloakProducerTest extends CamelTestSupport {
         
when(organizationsResource.get(anyString())).thenReturn(organizationResource);
         
when(organizationResource.identityProviders()).thenReturn(organizationIdpsResource);
         
when(organizationIdpsResource.get(anyString())).thenReturn(organizationIdpResource);
+        when(organizationIdpResource.delete()).thenReturn(response);
 
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedMessageCount(1);
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 10f5a47c1b89..98bc43a4c25c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -804,6 +804,21 @@ CamelContext of that provider. It now closes each of them 
only when no other `JC
 it returned the closed cache, whose operations throw `IllegalStateException`. 
This matters for code that calls a
 `JCacheManager` (for example one created by a custom `JCacheManagerFactory`) 
after it was closed.
 
+=== camel-keycloak - a failed create or delete fails the exchange, and a 
pojoRequest body is converted
+
+The producer operations that give the JAX-RS `Response` of Keycloak as the 
body, such as `createUser`, `deleteUser`,
+`createGroup`, `createClient` and `createOrganization`, now fail the exchange 
with a
+`jakarta.ws.rs.WebApplicationException` when Keycloak answers with a status 
other than 2xx, such as 409 (already
+exists) or 404 (not found). Before, the exchange completed and the route had 
to check the status of the `Response`.
+`deleteOrganization`, `removeOrganizationMember` and 
`unlinkOrganizationIdentityProvider` fail the same way. The
+`Response` body is now closed: its status and headers, such as `Location`, can 
still be read, but not its entity. The
+bulk operations count such a status as a failed item.
+
+With `pojoRequest=true`, a body that is not the Keycloak representation of the 
operation is converted: a `Map` or
+JSON text is mapped to it. A body that does not convert fails with an 
`InvalidPayloadException`; before, the operation
+did nothing and the body was kept. The elements of the `List` of 
`bulkCreateUsers` and `bulkUpdateUsers` are
+converted the same way; an element that does not convert fails the exchange 
before any call to Keycloak.
+
 === camel-spring-batch - the CamelSpringBatchJobName header needs 
jobFromHeader=true
 
 The producer now takes the job name from the `CamelSpringBatchJobName` header 
only when the endpoint has

Reply via email to