diff --git a/docs/content/docs/reference/components/jotform_v1.mdx b/docs/content/docs/reference/components/jotform_v1.mdx
index 4269f9ccf5b..911adeef3db 100644
--- a/docs/content/docs/reference/components/jotform_v1.mdx
+++ b/docs/content/docs/reference/components/jotform_v1.mdx
@@ -25,12 +25,26 @@ Version: 1
| Name | Label | Type | Description | Required |
|:---------------:|:--------------:|:------------:|:-------------------:|:--------:|
-| region | Region | STRING Options us, eu | | true |
+| region | Region | STRING Options us, eu, hipaa | | true |
| key | Key | STRING | | true |
| value | API Key | STRING | | true |
+## Connection Setup
+
+To connect ByteChef with Jotform, you need a Jotform API key.
+
+1. Log into your [Jotform account](https://www.jotform.com/myaccount/api).
+2. Navigate to the **API** Section.
+3. Click **Create New Key**.
+4. In the **Permissions** dropdown, select **Full Access**.
+5. Give your key a name, like `Bytechef Integration`.
+6. Copy the generated API Key.
+
+
+
+
@@ -96,6 +110,48 @@ Type: OBJECT
+## Triggers
+
+
+### New Submission
+Name: newSubmission
+
+`Triggers when someone submits a response to a form.`
+
+Type: DYNAMIC_WEBHOOK
+
+#### Properties
+
+| Name | Label | Type | Description | Required |
+|:---------------:|:--------------:|:------------:|:-------------------:|:--------:|
+| formId | Form ID | STRING | The ID of the form to watch for new submissions. | true |
+
+
+#### Output
+
+The output for this action is dynamic and may vary depending on the input parameters. To determine the exact structure of the output, you need to execute the action.
+
+#### JSON Example
+```json
+{
+ "label" : "New Submission",
+ "name" : "newSubmission",
+ "parameters" : {
+ "formId" : ""
+ },
+ "type" : "jotform/v1/newSubmission"
+}
+```
+#### How to find Form ID
+
+1. Log into your Jotform Account.
+2. Hover over the form in your dashboard and click **Edit Form**.
+3. Look at the URL in your browser's address bar. The URL will look similar to: `https://www.jotform.com/build/1111111111111`.
+4. The long number in the URL (between `/build/` and anything that follows) is your **Form ID**. In the example, the Form ID is `1111111111111`.
+
+
+
+
## What to do if your action is not listed here?
diff --git a/server/libs/modules/components/ai/llm/router/src/main/java/com/bytechef/component/ai/llm/router/model/RouterChatModel.java b/server/libs/modules/components/ai/llm/router/src/main/java/com/bytechef/component/ai/llm/router/model/RouterChatModel.java
index 246caebff8a..1e5204f5fe5 100644
--- a/server/libs/modules/components/ai/llm/router/src/main/java/com/bytechef/component/ai/llm/router/model/RouterChatModel.java
+++ b/server/libs/modules/components/ai/llm/router/src/main/java/com/bytechef/component/ai/llm/router/model/RouterChatModel.java
@@ -321,7 +321,7 @@ public Double getTemperature() {
}
public List getStop() {
- return stop;
+ return stop == null ? null : new ArrayList<>(stop);
}
public Integer getSeed() {
@@ -353,7 +353,7 @@ public Boolean getLogprobs() {
}
public Map getLogitBias() {
- return logitBias;
+ return logitBias == null ? null : new HashMap<>(logitBias);
}
public Double getFrequencyPenalty() {
diff --git a/server/libs/modules/components/jotform/openapi.yaml b/server/libs/modules/components/jotform/openapi.yaml
index 1f34fcdc587..4313d943f7d 100644
--- a/server/libs/modules/components/jotform/openapi.yaml
+++ b/server/libs/modules/components/jotform/openapi.yaml
@@ -12,6 +12,7 @@ paths:
summary: "Get Form Submissions"
description: "Get all submissions for a specific form."
operationId: "getFormSubmissions"
+ x-help: "https://docs.bytechef.io/reference/components/jotform_v1#get-form-submissions"
parameters:
- name: "formId"
description: "ID of the form to retrieve submissions for."
diff --git a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/JotformComponentHandler.java b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/JotformComponentHandler.java
index 0c03236073a..269d8498677 100644
--- a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/JotformComponentHandler.java
+++ b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/JotformComponentHandler.java
@@ -25,7 +25,9 @@
import com.bytechef.component.definition.ComponentDsl.ModifiableAuthorization;
import com.bytechef.component.definition.ComponentDsl.ModifiableComponentDefinition;
import com.bytechef.component.definition.ComponentDsl.ModifiableConnectionDefinition;
+import com.bytechef.component.definition.ComponentDsl.ModifiableTriggerDefinition;
import com.bytechef.component.definition.Property;
+import com.bytechef.component.jotform.trigger.JotformNewSubmissionTrigger;
import com.google.auto.service.AutoService;
import java.util.ArrayList;
import java.util.List;
@@ -39,6 +41,11 @@ public class JotformComponentHandler extends AbstractJotformComponentHandler {
private static final String REGION = "region";
+ @Override
+ public List getTriggers() {
+ return List.of(JotformNewSubmissionTrigger.TRIGGER_DEFINITION);
+ }
+
@Override
public ModifiableComponentDefinition modifyComponent(ModifiableComponentDefinition modifiableComponentDefinition) {
return modifiableComponentDefinition
@@ -66,7 +73,8 @@ public ModifiableConnectionDefinition modifyConnection(
.label("Region")
.options(
option("US (jotform.com)", "us"),
- option("EU (eu.jotform.com)", "eu"))
+ option("EU (eu.jotform.com)", "eu"),
+ option("HIPAA (hipaa-api.jotform.com)", "hipaa"))
.required(true));
modifiableAuthorization.properties(properties);
@@ -76,7 +84,14 @@ public ModifiableConnectionDefinition modifyConnection(
.baseUri((connectionParameters, context) -> {
String region = connectionParameters.getRequiredString(REGION);
- return region.equals("us") ? "https://api.jotform.com" : "https://eu-api.jotform.com";
- });
+ return switch (region) {
+ case "us" -> "https://api.jotform.com";
+ case "eu" -> "https://eu-api.jotform.com";
+ case "hipaa" -> "https://hipaa-api.jotform.com";
+ default -> throw new IllegalArgumentException("Invalid region: " + region);
+ };
+ })
+ .help("", "https://docs.bytechef.io/reference/components/jotform_v1#connection-setup")
+ .version(1);
}
}
diff --git a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/action/JotformGetFormSubmissionsAction.java b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/action/JotformGetFormSubmissionsAction.java
index 6252b628f62..20e1ef77016 100644
--- a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/action/JotformGetFormSubmissionsAction.java
+++ b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/action/JotformGetFormSubmissionsAction.java
@@ -67,7 +67,8 @@ public class JotformGetFormSubmissionsAction {
.required(false))
.metadata(
Map.of(
- "responseType", ResponseType.JSON))));
+ "responseType", ResponseType.JSON))))
+ .help("", "https://docs.bytechef.io/reference/components/jotform_v1#get-form-submissions");
private JotformGetFormSubmissionsAction() {
}
diff --git a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/trigger/JotformNewSubmissionTrigger.java b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/trigger/JotformNewSubmissionTrigger.java
new file mode 100644
index 00000000000..21a60a97a9d
--- /dev/null
+++ b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/trigger/JotformNewSubmissionTrigger.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2025 ByteChef
+ *
+ * Licensed 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
+ *
+ * https://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 com.bytechef.component.jotform.trigger;
+
+import static com.bytechef.component.definition.ComponentDsl.string;
+import static com.bytechef.component.definition.ComponentDsl.trigger;
+
+import com.bytechef.component.definition.ComponentDsl.ModifiableTriggerDefinition;
+import com.bytechef.component.definition.Context.Http;
+import com.bytechef.component.definition.Parameters;
+import com.bytechef.component.definition.TriggerContext;
+import com.bytechef.component.definition.TriggerDefinition.HttpHeaders;
+import com.bytechef.component.definition.TriggerDefinition.HttpParameters;
+import com.bytechef.component.definition.TriggerDefinition.OptionsFunction;
+import com.bytechef.component.definition.TriggerDefinition.TriggerType;
+import com.bytechef.component.definition.TriggerDefinition.WebhookBody;
+import com.bytechef.component.definition.TriggerDefinition.WebhookEnableOutput;
+import com.bytechef.component.definition.TriggerDefinition.WebhookMethod;
+import com.bytechef.component.definition.TypeReference;
+import com.bytechef.component.jotform.util.JotformUtils;
+import java.util.Map;
+
+/**
+ * @author Monika Kušter
+ */
+public class JotformNewSubmissionTrigger {
+
+ public static final String FORM_ID = "formId";
+ public static final String WEBHOOK_URL = "webhookURL";
+
+ public static final ModifiableTriggerDefinition TRIGGER_DEFINITION = trigger("newSubmission")
+ .title("New Submission")
+ .description("Triggers when someone submits a response to a form.")
+ .help("", "https://docs.bytechef.io/reference/components/jotform_v1#new-submission")
+ .type(TriggerType.DYNAMIC_WEBHOOK)
+ .properties(
+ string(FORM_ID)
+ .label("Form ID")
+ .description("The ID of the form to watch for new submissions.")
+ .options((OptionsFunction) JotformUtils::getFormIdOptions)
+ .required(true))
+ .output()
+ .webhookDisable(JotformNewSubmissionTrigger::webhookDisable)
+ .webhookEnable(JotformNewSubmissionTrigger::webhookEnable)
+ .webhookRequest(JotformNewSubmissionTrigger::webhookRequest);
+
+ private JotformNewSubmissionTrigger() {
+ }
+
+ protected static void webhookDisable(
+ Parameters inputParameters, Parameters connectionParameters, Parameters outputParameters,
+ String workflowExecutionId, TriggerContext triggerContext) {
+
+ Map body = triggerContext
+ .http(http -> http.get("/form/%s/webhooks".formatted(inputParameters.getRequiredString(FORM_ID))))
+ .configuration(Http.responseType(Http.ResponseType.JSON))
+ .execute()
+ .getBody(new TypeReference<>() {});
+
+ if (body.get("content") instanceof Map, ?> map) {
+ for (Map.Entry, ?> entry : map.entrySet()) {
+ Object value = entry.getValue();
+
+ if (value.equals(outputParameters.getRequiredString(WEBHOOK_URL))) {
+ triggerContext
+ .http(http -> http.delete(
+ "/form/%s/webhooks/%s".formatted(inputParameters.getRequiredString(FORM_ID),
+ entry.getKey())))
+ .execute();
+
+ break;
+ }
+ }
+ }
+ }
+
+ protected static WebhookEnableOutput webhookEnable(
+ Parameters inputParameters, Parameters connectionParameters, String webhookUrl, String workflowExecutionId,
+ TriggerContext triggerContext) {
+
+ triggerContext
+ .http(http -> http.post("/form/%s/webhooks".formatted(inputParameters.getRequiredString(FORM_ID))))
+ .header("Content-Type", "multipart/form-data")
+ .body(Http.Body.of(Map.of(WEBHOOK_URL, webhookUrl), Http.BodyContentType.FORM_DATA))
+ .configuration(Http.responseType(Http.ResponseType.JSON))
+ .execute();
+
+ return new WebhookEnableOutput(Map.of(WEBHOOK_URL, webhookUrl), null);
+ }
+
+ protected static Object webhookRequest(
+ Parameters inputParameters, Parameters connectionParameters, HttpHeaders headers,
+ HttpParameters parameters, WebhookBody body, WebhookMethod method, Parameters webhookEnableOutputParameters,
+ TriggerContext context) {
+
+ Map content = body.getContent(new TypeReference<>() {});
+
+ Object o = content.get("rawRequest");
+
+ if (o instanceof String s) {
+ content.put("parsedRawRequest", context.json(json -> json.read(s)));
+ }
+
+ return content;
+ }
+}
diff --git a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/util/JotformUtils.java b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/util/JotformUtils.java
index 59bea893ca1..636493a63d1 100644
--- a/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/util/JotformUtils.java
+++ b/server/libs/modules/components/jotform/src/main/java/com/bytechef/component/jotform/util/JotformUtils.java
@@ -39,20 +39,26 @@ public static List