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

luigidemasi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit a054da0bc932b006fe7e379c72e8f90018d4c93d
Author: Luigi De Masi <[email protected]>
AuthorDate: Wed Sep 30 20:29:42 2026 +0200

    CAMEL-25201: Make the TypeSafe AI API path configurable
    
    Expose apiPath on component and endpoint configuration with /v1/systemone
    as the default. Preserve base URL prefixes and reuse the managed endpoint
    configuration for semantic routes. Cover URL construction and configuration
    inheritance with HTTP tests, and update documentation and generated 
metadata.
    
    Co-authored-by: Codex <[email protected]>
    Signed-off-by: Luigi De Masi <[email protected]>
---
 .../camel/catalog/components/typesafe-ai.json      |  58 ++++-----
 .../camel/catalog/docs/typesafe-ai-component.adoc  |  24 +++-
 .../typesafeai/TypeSafeAiComponentConfigurer.java  |   6 +
 .../typesafeai/TypeSafeAiEndpointConfigurer.java   |   6 +
 .../typesafeai/TypeSafeAiEndpointUriFactory.java   |   3 +-
 .../camel/component/typesafeai/typesafe-ai.json    |  58 ++++-----
 .../src/main/docs/typesafe-ai-component.adoc       |  24 +++-
 .../component/typesafeai/TypeSafeAiClient.java     |   4 +-
 .../typesafeai/TypeSafeAiConfiguration.java        |  25 +++-
 .../typesafeai/TypeSafeAiApiPathTest.java          | 138 +++++++++++++++++++++
 .../typesafeai/TypeSafeAiTestSupport.java          |   2 +-
 .../dsl/TypesafeAiComponentBuilderFactory.java     |  25 +++-
 .../dsl/TypeSafeAiEndpointBuilderFactory.java      |  22 +++-
 13 files changed, 328 insertions(+), 67 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/typesafe-ai.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/typesafe-ai.json
index 96a854019318..18c9bff96dd6 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/typesafe-ai.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/typesafe-ai.json
@@ -24,36 +24,38 @@
     "remote": true
   },
   "componentProperties": {
-    "baseUrl": { "index": 0, "kind": "property", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends \/v1\/systemone. Redirects  [...]
-    "configuration": { "index": 1, "kind": "property", "displayName": 
"Configuration", "group": "producer", "label": "", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", "deprecated": 
false, "autowired": false, "secret": false, "description": "Default 
configuration shared by TypeSafe AI endpoints." },
-    "maxConcurrentRequests": { "index": 2, "kind": "property", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pre [...]
-    "model": { "index": 3, "kind": "property", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
-    "questions": { "index": 4, "kind": "property", "displayName": "Questions", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalua [...]
-    "questionsResource": { "index": 5, "kind": "property", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Scor [...]
-    "requestTimeout": { "index": 6, "kind": "property", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must b [...]
-    "state": { "index": 7, "kind": "property", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set,  [...]
-    "lazyStartProducer": { "index": 8, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
-    "resultProperty": { "index": 9, "kind": "property", "displayName": "Result 
Property", "group": "producer", "label": "producer", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
-    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
-    "threshold": { "index": 11, "kind": "property", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
-    "uncertainty": { "index": 12, "kind": "property", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Zer [...]
-    "uncertaintyPolicy": { "index": 13, "kind": "property", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "c [...]
-    "apiKey": { "index": 14, "kind": "property", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
+    "apiPath": { "index": 0, "kind": "property", "displayName": "Api Path", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "\/v1\/systemone", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API path appended to 
baseUrl. A leading slash is optional. Must be a n [...]
+    "baseUrl": { "index": 1, "kind": "property", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends apiPath, preserving any bas [...]
+    "configuration": { "index": 2, "kind": "property", "displayName": 
"Configuration", "group": "producer", "label": "", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", "deprecated": 
false, "autowired": false, "secret": false, "description": "Default 
configuration shared by TypeSafe AI endpoints." },
+    "maxConcurrentRequests": { "index": 3, "kind": "property", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pre [...]
+    "model": { "index": 4, "kind": "property", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
+    "questions": { "index": 5, "kind": "property", "displayName": "Questions", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalua [...]
+    "questionsResource": { "index": 6, "kind": "property", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Scor [...]
+    "requestTimeout": { "index": 7, "kind": "property", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must b [...]
+    "state": { "index": 8, "kind": "property", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set,  [...]
+    "lazyStartProducer": { "index": 9, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
+    "resultProperty": { "index": 10, "kind": "property", "displayName": 
"Result Property", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
+    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
+    "threshold": { "index": 12, "kind": "property", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
+    "uncertainty": { "index": 13, "kind": "property", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Zer [...]
+    "uncertaintyPolicy": { "index": 14, "kind": "property", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "c [...]
+    "apiKey": { "index": 15, "kind": "property", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
   },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "A logical name for the evaluation 
endpoint." },
-    "baseUrl": { "index": 1, "kind": "parameter", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends \/v1\/systemone. Redirects [...]
-    "maxConcurrentRequests": { "index": 2, "kind": "parameter", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pr [...]
-    "model": { "index": 3, "kind": "parameter", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
-    "questions": { "index": 4, "kind": "parameter", "displayName": 
"Questions", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalu [...]
-    "questionsResource": { "index": 5, "kind": "parameter", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Sco [...]
-    "requestTimeout": { "index": 6, "kind": "parameter", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must  [...]
-    "state": { "index": 7, "kind": "parameter", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set, [...]
-    "resultProperty": { "index": 8, "kind": "parameter", "displayName": 
"Result Property", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
-    "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
-    "threshold": { "index": 10, "kind": "parameter", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
-    "uncertainty": { "index": 11, "kind": "parameter", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Ze [...]
-    "uncertaintyPolicy": { "index": 12, "kind": "parameter", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": " [...]
-    "apiKey": { "index": 13, "kind": "parameter", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
+    "apiPath": { "index": 1, "kind": "parameter", "displayName": "Api Path", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "\/v1\/systemone", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API path appended to 
baseUrl. A leading slash is optional. Must be a  [...]
+    "baseUrl": { "index": 2, "kind": "parameter", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends apiPath, preserving any ba [...]
+    "maxConcurrentRequests": { "index": 3, "kind": "parameter", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pr [...]
+    "model": { "index": 4, "kind": "parameter", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
+    "questions": { "index": 5, "kind": "parameter", "displayName": 
"Questions", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalu [...]
+    "questionsResource": { "index": 6, "kind": "parameter", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Sco [...]
+    "requestTimeout": { "index": 7, "kind": "parameter", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must  [...]
+    "state": { "index": 8, "kind": "parameter", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set, [...]
+    "resultProperty": { "index": 9, "kind": "parameter", "displayName": 
"Result Property", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
+    "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produ [...]
+    "threshold": { "index": 11, "kind": "parameter", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
+    "uncertainty": { "index": 12, "kind": "parameter", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Ze [...]
+    "uncertaintyPolicy": { "index": 13, "kind": "parameter", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": " [...]
+    "apiKey": { "index": 14, "kind": "parameter", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
   }
 }
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-component.adoc
index 2d1e0cd0ec58..942b64630924 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/typesafe-ai-component.adoc
@@ -66,7 +66,8 @@ camel.component.typesafe-ai.max-concurrent-requests=64
 ----
 
 `apiKey` is a secret option. `baseUrl` defaults to `https://api.typesafe.ai`; 
the client
-appends `/v1/systemone`. A base path can address a proxy. HTTP redirects are 
not followed.
+appends `apiPath`, which defaults to `/v1/systemone`. A base path can address 
a proxy.
+HTTP redirects are not followed.
 Use HTTPS for the service; HTTP is useful for local testing.
 
 `model` defaults to `jev-latest`. Pin a version when tuning thresholds; 
aliases can change
@@ -74,6 +75,27 @@ behavior without a route change. The request map may 
explicitly override the end
 model for that request. The response's `model` identifies the model that 
answered.
 See https://docs.typesafe.ai/models[available models].
 
+=== Custom API path
+
+Set `apiPath` when a service or gateway exposes the supported TypeSafe AI 
request and
+response schema at a different path:
+
+[source,properties]
+----
+camel.component.typesafe-ai.base-url=http://localhost:8100
+camel.component.typesafe-ai.api-path=/v1/decision
+----
+
+The resulting request URL is `http://localhost:8100/v1/decision`. A path 
prefix in `baseUrl`
+is preserved: `http://localhost:8100/gateway/` produces
+`http://localhost:8100/gateway/v1/decision`. The leading slash in `apiPath` is 
optional.
+The path must not be blank or include a scheme, authority, query or fragment.
+
+An endpoint can override the component setting with 
`typesafe-ai:refund?apiPath=/v1/decision`.
+The Semantic language's TypeSafe AI adapter inherits the component setting 
even when the
+route contains no `typesafe-ai` endpoint. Changing the path does not change 
the required
+request and response schema.
+
 === Concurrent requests
 
 `maxConcurrentRequests` limits concurrent evaluations to 64 per endpoint by 
default and must
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiComponentConfigurer.java
 
b/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiComponentConfigurer.java
index 049cc2d4a171..dc15e479b3ce 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiComponentConfigurer.java
+++ 
b/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiComponentConfigurer.java
@@ -32,6 +32,8 @@ public class TypeSafeAiComponentConfigurer extends 
PropertyConfigurerSupport imp
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikey":
         case "apiKey": 
getOrCreateConfiguration(target).setApiKey(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "apipath":
+        case "apiPath": 
getOrCreateConfiguration(target).setApiPath(property(camelContext, 
java.lang.String.class, value)); return true;
         case "autowiredenabled":
         case "autowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
         case "baseurl":
@@ -63,6 +65,8 @@ public class TypeSafeAiComponentConfigurer extends 
PropertyConfigurerSupport imp
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikey":
         case "apiKey": return java.lang.String.class;
+        case "apipath":
+        case "apiPath": return java.lang.String.class;
         case "autowiredenabled":
         case "autowiredEnabled": return boolean.class;
         case "baseurl":
@@ -95,6 +99,8 @@ public class TypeSafeAiComponentConfigurer extends 
PropertyConfigurerSupport imp
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikey":
         case "apiKey": return getOrCreateConfiguration(target).getApiKey();
+        case "apipath":
+        case "apiPath": return getOrCreateConfiguration(target).getApiPath();
         case "autowiredenabled":
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "baseurl":
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointConfigurer.java
 
b/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointConfigurer.java
index 463d1e8a473f..4b4d65371980 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointConfigurer.java
+++ 
b/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointConfigurer.java
@@ -25,6 +25,8 @@ public class TypeSafeAiEndpointConfigurer extends 
PropertyConfigurerSupport impl
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikey":
         case "apiKey": 
target.getConfiguration().setApiKey(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "apipath":
+        case "apiPath": 
target.getConfiguration().setApiPath(property(camelContext, 
java.lang.String.class, value)); return true;
         case "baseurl":
         case "baseUrl": 
target.getConfiguration().setBaseUrl(property(camelContext, 
java.lang.String.class, value)); return true;
         case "lazystartproducer":
@@ -53,6 +55,8 @@ public class TypeSafeAiEndpointConfigurer extends 
PropertyConfigurerSupport impl
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikey":
         case "apiKey": return java.lang.String.class;
+        case "apipath":
+        case "apiPath": return java.lang.String.class;
         case "baseurl":
         case "baseUrl": return java.lang.String.class;
         case "lazystartproducer":
@@ -82,6 +86,8 @@ public class TypeSafeAiEndpointConfigurer extends 
PropertyConfigurerSupport impl
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikey":
         case "apiKey": return target.getConfiguration().getApiKey();
+        case "apipath":
+        case "apiPath": return target.getConfiguration().getApiPath();
         case "baseurl":
         case "baseUrl": return target.getConfiguration().getBaseUrl();
         case "lazystartproducer":
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointUriFactory.java
 
b/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointUriFactory.java
index f31f10cb2caa..b086097ca430 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointUriFactory.java
+++ 
b/components/camel-ai/camel-typesafe-ai/src/generated/java/org/apache/camel/component/typesafeai/TypeSafeAiEndpointUriFactory.java
@@ -24,8 +24,9 @@ public class TypeSafeAiEndpointUriFactory extends 
org.apache.camel.support.compo
     private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(14);
+        Set<String> props = new HashSet<>(15);
         props.add("apiKey");
+        props.add("apiPath");
         props.add("baseUrl");
         props.add("lazyStartProducer");
         props.add("maxConcurrentRequests");
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/component/typesafeai/typesafe-ai.json
 
b/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/component/typesafeai/typesafe-ai.json
index 96a854019318..18c9bff96dd6 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/component/typesafeai/typesafe-ai.json
+++ 
b/components/camel-ai/camel-typesafe-ai/src/generated/resources/META-INF/org/apache/camel/component/typesafeai/typesafe-ai.json
@@ -24,36 +24,38 @@
     "remote": true
   },
   "componentProperties": {
-    "baseUrl": { "index": 0, "kind": "property", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends \/v1\/systemone. Redirects  [...]
-    "configuration": { "index": 1, "kind": "property", "displayName": 
"Configuration", "group": "producer", "label": "", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", "deprecated": 
false, "autowired": false, "secret": false, "description": "Default 
configuration shared by TypeSafe AI endpoints." },
-    "maxConcurrentRequests": { "index": 2, "kind": "property", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pre [...]
-    "model": { "index": 3, "kind": "property", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
-    "questions": { "index": 4, "kind": "property", "displayName": "Questions", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalua [...]
-    "questionsResource": { "index": 5, "kind": "property", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Scor [...]
-    "requestTimeout": { "index": 6, "kind": "property", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must b [...]
-    "state": { "index": 7, "kind": "property", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set,  [...]
-    "lazyStartProducer": { "index": 8, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
-    "resultProperty": { "index": 9, "kind": "property", "displayName": "Result 
Property", "group": "producer", "label": "producer", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
-    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
-    "threshold": { "index": 11, "kind": "property", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
-    "uncertainty": { "index": 12, "kind": "property", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Zer [...]
-    "uncertaintyPolicy": { "index": 13, "kind": "property", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "c [...]
-    "apiKey": { "index": 14, "kind": "property", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
+    "apiPath": { "index": 0, "kind": "property", "displayName": "Api Path", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "\/v1\/systemone", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API path appended to 
baseUrl. A leading slash is optional. Must be a n [...]
+    "baseUrl": { "index": 1, "kind": "property", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends apiPath, preserving any bas [...]
+    "configuration": { "index": 2, "kind": "property", "displayName": 
"Configuration", "group": "producer", "label": "", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", "deprecated": 
false, "autowired": false, "secret": false, "description": "Default 
configuration shared by TypeSafe AI endpoints." },
+    "maxConcurrentRequests": { "index": 3, "kind": "property", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pre [...]
+    "model": { "index": 4, "kind": "property", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
+    "questions": { "index": 5, "kind": "property", "displayName": "Questions", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalua [...]
+    "questionsResource": { "index": 6, "kind": "property", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Scor [...]
+    "requestTimeout": { "index": 7, "kind": "property", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must b [...]
+    "state": { "index": 8, "kind": "property", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set,  [...]
+    "lazyStartProducer": { "index": 9, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": false, "description": 
"Whether the producer should be started lazy (on the first message). By 
starting lazy you can use this to allow CamelContext and routes to startup in 
situations where a producer may otherwise fail [...]
+    "resultProperty": { "index": 10, "kind": "property", "displayName": 
"Result Property", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
+    "autowiredEnabled": { "index": 11, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
+    "threshold": { "index": 12, "kind": "property", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
+    "uncertainty": { "index": 13, "kind": "property", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Zer [...]
+    "uncertaintyPolicy": { "index": 14, "kind": "property", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "c [...]
+    "apiKey": { "index": 15, "kind": "property", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
   },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "A logical name for the evaluation 
endpoint." },
-    "baseUrl": { "index": 1, "kind": "parameter", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends \/v1\/systemone. Redirects [...]
-    "maxConcurrentRequests": { "index": 2, "kind": "parameter", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pr [...]
-    "model": { "index": 3, "kind": "parameter", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
-    "questions": { "index": 4, "kind": "parameter", "displayName": 
"Questions", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalu [...]
-    "questionsResource": { "index": 5, "kind": "parameter", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Sco [...]
-    "requestTimeout": { "index": 6, "kind": "parameter", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must  [...]
-    "state": { "index": 7, "kind": "parameter", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set, [...]
-    "resultProperty": { "index": 8, "kind": "parameter", "displayName": 
"Result Property", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
-    "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
-    "threshold": { "index": 10, "kind": "parameter", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
-    "uncertainty": { "index": 11, "kind": "parameter", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Ze [...]
-    "uncertaintyPolicy": { "index": 12, "kind": "parameter", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": " [...]
-    "apiKey": { "index": 13, "kind": "parameter", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
+    "apiPath": { "index": 1, "kind": "parameter", "displayName": "Api Path", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "\/v1\/systemone", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API path appended to 
baseUrl. A leading slash is optional. Must be a  [...]
+    "baseUrl": { "index": 2, "kind": "parameter", "displayName": "Base Url", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "https:\/\/api.typesafe.ai", 
"configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API base URL. The 
client appends apiPath, preserving any ba [...]
+    "maxConcurrentRequests": { "index": 3, "kind": "parameter", "displayName": 
"Max Concurrent Requests", "group": "common", "label": "common", "required": 
false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 64, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Maximum concurrent 
evaluations per endpoint, shared by producers and pr [...]
+    "model": { "index": 4, "kind": "parameter", "displayName": "Model", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "jev-latest", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The model ID or alias. 
Use a versioned ID to pin decision behavior." },
+    "questions": { "index": 5, "kind": "parameter", "displayName": 
"Questions", "group": "common", "label": "common", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "A JSON object mapping 
question names to Noul, Choice or Score question objects. When set, producers 
evalu [...]
+    "questionsResource": { "index": 6, "kind": "parameter", "displayName": 
"Questions Resource", "group": "common", "label": "common", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Camel resource URI for a 
UTF-8 JSON object mapping question names to Noul, Choice or Sco [...]
+    "requestTimeout": { "index": 7, "kind": "parameter", "displayName": 
"Request Timeout", "group": "common", "label": "common", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The timeout in 
milliseconds for the complete HTTP request and response body. Must  [...]
+    "state": { "index": 8, "kind": "parameter", "displayName": "State", 
"group": "common", "label": "common", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The Simple expression 
selecting state for configured producer questions and the TypeSafe AI language. 
If not set, [...]
+    "resultProperty": { "index": 9, "kind": "parameter", "displayName": 
"Result Property", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Store the producer 
response in this exchange property, preserving the original message body." },
+    "lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produ [...]
+    "threshold": { "index": 11, "kind": "parameter", "displayName": 
"Threshold", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.5, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default inclusive 
probability threshold for the TypeSafe AI language. Must be within 0,1." },
+    "uncertainty": { "index": 12, "kind": "parameter", "displayName": 
"Uncertainty", "group": "advanced", "label": "advanced", "required": false, 
"type": "number", "javaType": "double", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": 0.0, "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "Default half-width of 
the inclusive uncertainty band for the TypeSafe AI language. Ze [...]
+    "uncertaintyPolicy": { "index": 13, "kind": "parameter", "displayName": 
"Uncertainty Policy", "group": "advanced", "label": "advanced", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.language.typesafeai.TypeSafeAiLanguage.UncertaintyPolicy", 
"enum": [ "NonMatch", "Fail" ], "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": "NonMatch", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": " [...]
+    "apiKey": { "index": 14, "kind": "parameter", "displayName": "Api Key", 
"group": "security", "label": "security", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": true, "security": "secret", "configurationClass": 
"org.apache.camel.component.typesafeai.TypeSafeAiConfiguration", 
"configurationField": "configuration", "description": "The API key used for 
Bearer authentication." }
   }
 }
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-component.adoc
 
b/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-component.adoc
index 2d1e0cd0ec58..942b64630924 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-component.adoc
+++ 
b/components/camel-ai/camel-typesafe-ai/src/main/docs/typesafe-ai-component.adoc
@@ -66,7 +66,8 @@ camel.component.typesafe-ai.max-concurrent-requests=64
 ----
 
 `apiKey` is a secret option. `baseUrl` defaults to `https://api.typesafe.ai`; 
the client
-appends `/v1/systemone`. A base path can address a proxy. HTTP redirects are 
not followed.
+appends `apiPath`, which defaults to `/v1/systemone`. A base path can address 
a proxy.
+HTTP redirects are not followed.
 Use HTTPS for the service; HTTP is useful for local testing.
 
 `model` defaults to `jev-latest`. Pin a version when tuning thresholds; 
aliases can change
@@ -74,6 +75,27 @@ behavior without a route change. The request map may 
explicitly override the end
 model for that request. The response's `model` identifies the model that 
answered.
 See https://docs.typesafe.ai/models[available models].
 
+=== Custom API path
+
+Set `apiPath` when a service or gateway exposes the supported TypeSafe AI 
request and
+response schema at a different path:
+
+[source,properties]
+----
+camel.component.typesafe-ai.base-url=http://localhost:8100
+camel.component.typesafe-ai.api-path=/v1/decision
+----
+
+The resulting request URL is `http://localhost:8100/v1/decision`. A path 
prefix in `baseUrl`
+is preserved: `http://localhost:8100/gateway/` produces
+`http://localhost:8100/gateway/v1/decision`. The leading slash in `apiPath` is 
optional.
+The path must not be blank or include a scheme, authority, query or fragment.
+
+An endpoint can override the component setting with 
`typesafe-ai:refund?apiPath=/v1/decision`.
+The Semantic language's TypeSafe AI adapter inherits the component setting 
even when the
+route contains no `typesafe-ai` endpoint. Changing the path does not change 
the required
+request and response schema.
+
 === Concurrent requests
 
 `maxConcurrentRequests` limits concurrent evaluations to 64 per endpoint by 
default and must
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiClient.java
 
b/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiClient.java
index 393d79053a23..8b4d3c4712cb 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiClient.java
+++ 
b/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiClient.java
@@ -32,6 +32,7 @@ import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import org.apache.camel.util.URISupport;
 import org.apache.camel.util.json.JsonObject;
 import org.apache.camel.util.json.Jsoner;
 
@@ -52,8 +53,7 @@ final class TypeSafeAiClient implements AutoCloseable {
         maxConcurrentRequests = configuration.getMaxConcurrentRequests();
         apiKey = configuration.getApiKey();
         model = configuration.getModel();
-        String baseUrl = configuration.getBaseUrl();
-        uri = URI.create((baseUrl.endsWith("/") ? baseUrl.substring(0, 
baseUrl.length() - 1) : baseUrl) + "/v1/systemone");
+        uri = URI.create(URISupport.joinPaths(configuration.getBaseUrl(), 
configuration.getApiPath()));
         http = 
HttpClient.newBuilder().connectTimeout(timeout).followRedirects(HttpClient.Redirect.NEVER).build();
     }
 
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiConfiguration.java
 
b/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiConfiguration.java
index b23be21886cc..9b814600fd82 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiConfiguration.java
+++ 
b/components/camel-ai/camel-typesafe-ai/src/main/java/org/apache/camel/component/typesafeai/TypeSafeAiConfiguration.java
@@ -31,6 +31,8 @@ public class TypeSafeAiConfiguration implements Cloneable {
     private String apiKey;
     @UriParam(label = "common", defaultValue = "https://api.typesafe.ai";)
     private String baseUrl = "https://api.typesafe.ai";;
+    @UriParam(label = "common", defaultValue = "/v1/systemone")
+    private String apiPath = "/v1/systemone";
     @UriParam(label = "common", defaultValue = "jev-latest")
     private String model = "jev-latest";
     @UriParam(label = "common", defaultValue = "30000")
@@ -147,11 +149,23 @@ public class TypeSafeAiConfiguration implements Cloneable 
{
         return baseUrl;
     }
 
-    /** The API base URL. The client appends /v1/systemone. Redirects are not 
followed. */
+    /** The API base URL. The client appends apiPath, preserving any base 
path. Redirects are not followed. */
     public void setBaseUrl(String baseUrl) {
         this.baseUrl = baseUrl;
     }
 
+    public String getApiPath() {
+        return apiPath;
+    }
+
+    /**
+     * The API path appended to baseUrl. A leading slash is optional. Must be 
a non-blank path without a scheme,
+     * authority, query or fragment. The service must implement the supported 
TypeSafe AI request and response schema.
+     */
+    public void setApiPath(String apiPath) {
+        this.apiPath = apiPath;
+    }
+
     public String getModel() {
         return model;
     }
@@ -200,6 +214,7 @@ public class TypeSafeAiConfiguration implements Cloneable {
         ObjectHelper.notNull(apiKey, "apiKey");
         ObjectHelper.notNull(model, "model");
         ObjectHelper.notNull(baseUrl, "baseUrl");
+        ObjectHelper.notNull(apiPath, "apiPath");
         if (apiKey.isBlank() || model.isBlank()) {
             throw new IllegalArgumentException("apiKey and model must not be 
blank");
         }
@@ -211,6 +226,14 @@ public class TypeSafeAiConfiguration implements Cloneable {
                 || uri.getHost() == null || uri.getUserInfo() != null || 
uri.getFragment() != null || uri.getQuery() != null) {
             throw new IllegalArgumentException("baseUrl must be an HTTP(S) URL 
without user information, query or fragment");
         }
+        if (apiPath.isBlank()) {
+            throw new IllegalArgumentException("apiPath must not be blank");
+        }
+        URI path = URI.create(apiPath);
+        if (path.getScheme() != null || path.getRawAuthority() != null || 
path.getQuery() != null
+                || path.getFragment() != null) {
+            throw new IllegalArgumentException("apiPath must be a path without 
a scheme, authority, query or fragment");
+        }
         if (requestTimeout <= 0) {
             throw new IllegalArgumentException("requestTimeout must be 
positive");
         }
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiApiPathTest.java
 
b/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiApiPathTest.java
new file mode 100644
index 000000000000..38248cd7131a
--- /dev/null
+++ 
b/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiApiPathTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.typesafeai;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.main.Main;
+import org.apache.camel.semantic.SemanticQuestion;
+import org.apache.camel.semantic.SemanticQuestions;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class TypeSafeAiApiPathTest extends TypeSafeAiTestSupport {
+    private final ConcurrentLinkedQueue<String> paths = new 
ConcurrentLinkedQueue<>();
+
+    @BeforeEach
+    void capturePaths() {
+        server.removeContext("/v1/systemone");
+        server.createContext("/", exchange -> {
+            paths.add(exchange.getRequestURI().toString());
+            handle(exchange);
+        });
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "'', /v1/systemone", "/, /v1/systemone",
+            "/gateway, /gateway/v1/systemone", "/gateway/, 
/gateway/v1/systemone",
+            "/gateway//, /gateway//v1/systemone" })
+    void defaultPathPreservesBaseUrlBehavior(String prefix, String 
expectedPath) {
+        TypeSafeAiConfiguration configuration
+                = context.getComponent("typesafe-ai", 
TypeSafeAiComponent.class).getConfiguration();
+        configuration.setBaseUrl(configuration.getBaseUrl() + prefix);
+
+        JsonObject response = template.requestBody("typesafe-ai:default", 
request("Refund"), JsonObject.class);
+
+        assertThat(response.getJsonObject("answers")).containsKey("predicate");
+        assertThat(paths).containsExactly(expectedPath);
+    }
+
+    @ParameterizedTest
+    @CsvSource({
+            "'', /v1/decision, /v1/decision", "'', v1/decision, /v1/decision",
+            "/, /v1/decision, /v1/decision", "/, v1/decision, /v1/decision",
+            "/gateway, /v1/decision, /gateway/v1/decision", "/gateway, 
v1/decision, /gateway/v1/decision",
+            "/gateway/, /v1/decision, /gateway/v1/decision", "/gateway/, 
v1/decision, /gateway/v1/decision",
+            "/gateway/, /v1/decision/, /gateway/v1/decision/", "/gateway/, /, 
/gateway/" })
+    void endpointPathOverridesComponentDefault(String prefix, String apiPath, 
String expectedPath) {
+        TypeSafeAiConfiguration configuration
+                = context.getComponent("typesafe-ai", 
TypeSafeAiComponent.class).getConfiguration();
+        configuration.setBaseUrl(configuration.getBaseUrl() + prefix);
+        configuration.setApiPath("/component");
+
+        JsonObject response
+                = template.requestBody("typesafe-ai:custom?apiPath=" + 
apiPath, request("Refund"), JsonObject.class);
+
+        assertThat(response.getJsonObject("answers")).containsKey("predicate");
+        assertThat(paths).containsExactly(expectedPath);
+        assertThat(configuration.getApiPath()).isEqualTo("/component");
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = { false, true })
+    void componentPropertiesConfigureProducerAndSemanticAdapter(boolean 
semantic) throws Exception {
+        Main main = new Main();
+        main.addProperty("camel.component.typesafe-ai.api-key", "test-key");
+        main.addProperty("camel.component.typesafe-ai.base-url",
+                "http://127.0.0.1:"; + server.getAddress().getPort() + 
"/gateway/");
+        main.addProperty("camel.component.typesafe-ai.api-path", 
"/v1/decision");
+        main.configure().addRoutesBuilder(new RouteBuilder() {
+            @Override
+            public void configure() {
+                if (semantic) {
+                    SemanticQuestions.get(getContext()).replace("test", 
Map.of("refund", new SemanticQuestion(
+                            SemanticQuestion.Type.BOOLEAN, "Refund 
requested?", null,
+                            Map.of(), List.of(), 0.5, 0, 
SemanticQuestion.UncertaintyPolicy.FAIL)));
+                    from("direct:request").setBody().language("semantic", 
"ref:refund");
+                } else {
+                    from("direct:request").to("typesafe-ai:configured");
+                }
+            }
+        });
+        respond = request -> result(Map.of(semantic ? "question" : 
"predicate", Map.of("type", "noul", "noul", 0.9)));
+        try {
+            main.start();
+            try (var producer = 
main.getCamelContext().createProducerTemplate()) {
+                Object response = producer.requestBody("direct:request", 
semantic ? "Refund" : request("Refund"));
+                if (semantic) {
+                    assertThat(response).isEqualTo(true);
+                } else {
+                    assertThat(((JsonObject) 
response).getJsonObject("answers")).containsKey("predicate");
+                }
+                assertThat(paths).containsExactly("/gateway/v1/decision");
+                assertThat(requests).hasSize(1);
+                assertThat(requests.peek().get("state")).isEqualTo("Refund");
+                assertThat(authorization).containsExactly("Bearer test-key");
+            }
+        } finally {
+            main.stop();
+        }
+    }
+
+    @ParameterizedTest
+    @NullAndEmptySource
+    @ValueSource(strings = {
+            " ", "https://example.com/v1/decision";, 
"//example.com/v1/decision", "/v1/decision?query=value",
+            "/v1/decision#fragment", "/invalid path", "/invalid%path" })
+    void rejectsInvalidPathsBeforeSending(String apiPath) {
+        context.getComponent("typesafe-ai", 
TypeSafeAiComponent.class).getConfiguration().setApiPath(apiPath);
+
+        assertThatThrownBy(() -> 
context.getEndpoint("typesafe-ai:invalid")).isInstanceOf(Exception.class);
+        assertThat(paths).isEmpty();
+    }
+}
diff --git 
a/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiTestSupport.java
 
b/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiTestSupport.java
index e32f630421e5..a282ee45dd3a 100644
--- 
a/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiTestSupport.java
+++ 
b/components/camel-ai/camel-typesafe-ai/src/test/java/org/apache/camel/component/typesafeai/TypeSafeAiTestSupport.java
@@ -87,7 +87,7 @@ abstract class TypeSafeAiTestSupport {
         }
     }
 
-    private void handle(HttpExchange exchange) throws IOException {
+    void handle(HttpExchange exchange) throws IOException {
         try {
             JsonObject request = (JsonObject) Jsoner.deserialize(
                     new String(exchange.getRequestBody().readAllBytes(), 
StandardCharsets.UTF_8));
diff --git 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/TypesafeAiComponentBuilderFactory.java
 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/TypesafeAiComponentBuilderFactory.java
index 0b906952c114..cec32d2b62f6 100644
--- 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/TypesafeAiComponentBuilderFactory.java
+++ 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/TypesafeAiComponentBuilderFactory.java
@@ -52,8 +52,28 @@ public interface TypesafeAiComponentBuilderFactory {
     
         
         /**
-         * The API base URL. The client appends /v1/systemone. Redirects are 
not
-         * followed.
+         * The API path appended to baseUrl. A leading slash is optional. Must
+         * be a non-blank path without a scheme, authority, query or fragment.
+         * The service must implement the supported TypeSafe AI request and
+         * response schema.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Default: /v1/systemone
+         * Group: common
+         * 
+         * @param apiPath the value to set
+         * @return the dsl builder
+         */
+        default TypesafeAiComponentBuilder apiPath(java.lang.String apiPath) {
+            doSetProperty("apiPath", apiPath);
+            return this;
+        }
+    
+        
+        /**
+         * The API base URL. The client appends apiPath, preserving any base
+         * path. Redirects are not followed.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
          * 
@@ -341,6 +361,7 @@ public interface TypesafeAiComponentBuilderFactory {
                 String name,
                 Object value) {
             switch (name) {
+            case "apiPath": getOrCreateConfiguration((TypeSafeAiComponent) 
component).setApiPath((java.lang.String) value); return true;
             case "baseUrl": getOrCreateConfiguration((TypeSafeAiComponent) 
component).setBaseUrl((java.lang.String) value); return true;
             case "configuration": ((TypeSafeAiComponent) 
component).setConfiguration((org.apache.camel.component.typesafeai.TypeSafeAiConfiguration)
 value); return true;
             case "maxConcurrentRequests": 
getOrCreateConfiguration((TypeSafeAiComponent) 
component).setMaxConcurrentRequests((int) value); return true;
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TypeSafeAiEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TypeSafeAiEndpointBuilderFactory.java
index 3ed41187a75d..d43faded2df3 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TypeSafeAiEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TypeSafeAiEndpointBuilderFactory.java
@@ -45,8 +45,26 @@ public interface TypeSafeAiEndpointBuilderFactory {
         }
 
         /**
-         * The API base URL. The client appends /v1/systemone. Redirects are 
not
-         * followed.
+         * The API path appended to baseUrl. A leading slash is optional. Must
+         * be a non-blank path without a scheme, authority, query or fragment.
+         * The service must implement the supported TypeSafe AI request and
+         * response schema.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Default: /v1/systemone
+         * Group: common
+         * 
+         * @param apiPath the value to set
+         * @return the dsl builder
+         */
+        default TypeSafeAiEndpointBuilder apiPath(String apiPath) {
+            doSetProperty("apiPath", apiPath);
+            return this;
+        }
+        /**
+         * The API base URL. The client appends apiPath, preserving any base
+         * path. Redirects are not followed.
          * 
          * The option is a: <code>java.lang.String</code> type.
          * 

Reply via email to