Embed on your site
You can embed a FlowGenie form inside your own application and handle the UI yourself. The steps are straightforward:
- Build the form using the visual form builder inside FlowGenie.
- Fetch the configuration with a GET request to
https://app.flowgenie.pro/api/headless/forms/{slug} - Render the form in your app by looping through this configuration. Use the
typeof each question to decide which input to render. Use the questionkeyas the field name when collecting values. - Submit responses back to
https://app.flowgenie.pro/api/headless/forms/{slug}/submitwith a POST request.
The response contains a JSON object similar to the structure used in the form builder. It has an array of pages (for now only one page), each containing sections, which in turn contain an array of rows of questions.
If you are using react, you should use the React Form Component that we provide, which handles displaying all question types, validation, condtional questions, etc. And it provides a nice starting point for styles, which you can override. Click here to learn more.
API Endpoints
- GET
https://app.flowgenie.pro/api/headless/forms/{slug}- Fetch form configuration - POST
https://app.flowgenie.pro/api/headless/forms/{slug}/submit- Submit form data
Both endpoints require an Authorization: Bearer YOUR_API_KEY header if the form is not public.
Example
SDK
If you want to avoid wiring up raw fetch calls, you can use the FlowGenie SDK to fetchForm and submitForm directly.
import { createClient } from '@flowgenie/sdk'
const client = createClient({
apiKey: process.env.FLOWGENIE_API_KEY,
baseUrl: 'https://app.flowgenie.pro'
})
const form = await client.fetchForm({ id: 'form-id' })
await client.submitForm({
id: 'form-id',
data: {
name: 'Ada Lovelace',
email: 'ada@example.com'
}
})
Public forms can be fetched and submitted with a slug instead of an id.
JavaScript
<!DOCTYPE html>
<html>
<head>
<title>FlowGenie Form</title>
<style>
.form-container { max-width: 600px; margin: 0 auto; padding: 20px; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input, textarea, select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; }
button { background: #3b82f6; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background: #2563eb; }
</style>
</head>
<body>
<div class="form-container">
<form id="flowgenie-form">
<div id="form-questions"></div>
<button type="submit">Submit</button>
</form>
</div>
<script>
const slug = 'your-form-slug';
const apiKey = 'YOUR_API_KEY';
let formConfig = null;
const answers = {};
// Fetch form configuration
async function loadForm() {
const response = await fetch(`https://app.flowgenie.pro/api/headless/forms/${slug}`, {
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
formConfig = await response.json();
renderForm();
}
// Render form questions
function renderForm() {
const container = document.getElementById('form-questions');
container.innerHTML = '';
formConfig.pages[0].sections.forEach(section => {
section.questions.forEach(row => {
row.forEach(question => {
const div = document.createElement('div');
div.className = 'form-group';
const label = document.createElement('label');
label.textContent = question.label + (question.required ? ' *' : '');
div.appendChild(label);
let input;
switch (question.type) {
case 'text':
case 'email':
case 'password':
input = document.createElement('input');
input.type = question.type;
input.placeholder = question.placeholder || '';
break;
case 'multiline':
input = document.createElement('textarea');
input.placeholder = question.placeholder || '';
break;
case 'number':
input = document.createElement('input');
input.type = 'number';
input.placeholder = question.placeholder || '';
break;
case 'checkbox':
input = document.createElement('input');
input.type = 'checkbox';
break;
case 'select':
input = document.createElement('select');
const defaultOption = document.createElement('option');
defaultOption.value = '';
defaultOption.textContent = 'Select...';
input.appendChild(defaultOption);
question.options?.forEach(opt => {
const option = document.createElement('option');
option.value = opt.value;
option.textContent = opt.label;
input.appendChild(option);
});
break;
case 'date':
input = document.createElement('input');
input.type = 'date';
break;
default:
return;
}
input.id = question.key;
input.required = question.required || false;
input.addEventListener('change', (e) => {
if (question.type === 'checkbox') {
answers[question.key] = e.target.checked;
} else {
answers[question.key] = e.target.value;
}
});
div.appendChild(input);
container.appendChild(div);
});
});
});
}
// Handle form submission
document.getElementById('flowgenie-form').addEventListener('submit', async (e) => {
e.preventDefault();
const response = await fetch(`https://app.flowgenie.pro/api/headless/forms/${slug}/submit`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify(answers)
});
const result = await response.json();
console.log('Form submitted:', result);
alert('Form submitted successfully!');
});
// Load form on page load
loadForm();
</script>
</body>
</html>This approach lets you keep complete control over the look and feel while relying on FlowGenie for form management and submission handling.