Skip to Content
FormsEmbed on your site

Embed on your site

You can embed a FlowGenie form inside your own application and handle the UI yourself. The steps are straightforward:

  1. Build the form using the visual form builder inside FlowGenie.
  2. Fetch the configuration with a GET request to https://app.flowgenie.pro/api/headless/forms/{slug}
  3. Render the form in your app by looping through this configuration. Use the type of each question to decide which input to render. Use the question key as the field name when collecting values.
  4. Submit responses back to https://app.flowgenie.pro/api/headless/forms/{slug}/submit with 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.

Last updated on