Skip to content

Integrate a form into your site (no iframe)

Besides the public URL and iframe embedding, you can build the form in your own website and submit it directly to Floogos with a POST from the browser (cross-domain integration, no iframe), handling the response yourself.


Since the submission is made from your domain to the Floogos server, that origin

must be authorized. In the installation you set the environment variable:

Ventana de terminal
EXTRA_CORS_ORIGINS="https://intranet.yourcompany.com,*.yourcompany.com"
  • Accepts several comma-separated domains.
  • Supports exact origin (https://intranet.yourcompany.com) and subdomain wildcard (*.yourcompany.com).
  • After setting it, the service is restarted.

POST https://<your-floogos-installation>/f/{HASH}/submit
Content-Type: application/json
  • {HASH} is the form’s public identifier (the same one in its public URL .../f/{HASH}).
  • The body is JSON with one key per field, using the field’s technical name (name), not the visible label.
  • In the form editor, each field has its name (identifier).
  • Or by querying the form definition: GET https://<host>/f/{HASH}/data → returns the fields with their name, type, required and validations (useful to build and validate on your site).

<form id="myForm">
<input name="name" required />
<input name="email" type="email" required />
<textarea name="message" maxlength="500"></textarea>
<button type="submit">Send</button>
</form>
<script>
const HASH = "abc123def456"; // form public hash
const BASE = "https://floogos.yourcompany.com"; // your Floogos installation
document.getElementById("myForm").addEventListener("submit", async (e) => {
e.preventDefault();
const form = e.target;
const payload = {
name: form.name.value,
email: form.email.value,
message: form.message.value,
};
try {
const resp = await fetch(`${BASE}/f/${HASH}/submit`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
// credentials: "include" // only if the form uses a cookie-based security group
});
const result = await resp.json();
if (resp.ok && result.success) {
if (result.redirect) {
window.location.href = result.redirect;
} else {
alert(result.message || "Form submitted successfully");
// result.submissionId → submission id; result.data → workflow response
}
} else {
alert(result.error || "The form could not be submitted");
}
} catch (err) {
alert("Network error submitting the form");
}
});
</script>

Success (HTTP 200):

{
"success": true,
"message": "Form submitted successfully",
"submissionId": 12345,
"redirect": "https://…",
"data": { }
}

redirect appears only if the form is configured to redirect; data only if the form triggers a workflow with a structured response.

Common errors:

HTTPResponseMeaning
404{ "error": "Form not found or unavailable" }Wrong hash or form not published.
401{ "error": "Group authentication required.", "requires_group_auth": true }The form has a security group.
401{ "error": "Authentication required…" }The form requires login.
400{ "error": "…" }Data validation.

If the form has no restrictions, the above is enough. If it’s secured:

  • Security group: obtain a realm token via the group’s authentication flow and send it in the x-form-realm-token: <token> header (or use credentials: "include" with the cookie session).
  • Form with login: include the token in the body as __auth_token.

  • Attachments: file fields are sent as an object with base64 content ({ filename, mime, content_base64 }).
  • Validation: replicate the form’s validations on your site (required, max length, pattern) using GET /f/{HASH}/data. The server validates on receipt anyway.
  • HTTPS: cross-domain browser submission requires HTTPS on both sides.