From zero to rendered form in under 2 minutes. No SDK required, just a POST request.
Avg. time to first form: 55 secondsCreate a free API key by sending a POST request with your email address. The API key is returned immediately and starts with ff_live_. No credit card required.
curl -X POST https://formforge-api.vercel.app/api/signup \ -H "Content-Type: application/json" \ -d '{ "email": "you@example.com" }'
The response includes your API key:
{
"message": "API key created successfully.",
"api_key": "ff_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"tier": "free",
"rate_limit": { "forms_per_day": 20 }
}
Authorization: Bearer YOUR_KEY in all subsequent requests.
You can also get a key instantly through the signup form on the homepage or via the dashboard.
Send a JSON form definition to the rendering endpoint. At minimum, you need a fields array with at least one field. Each field requires name, type, and label.
curl -X POST https://formforge-api.vercel.app/api/json-to-form \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ff_live_your_key_here" \ -d '{ "title": "Contact Us", "fields": [ { "name": "name", "type": "text", "label": "Full Name", "required": true }, { "name": "email", "type": "email", "label": "Email", "required": true }, { "name": "message", "type": "textarea", "label": "Message" } ] }'
The API returns a JSON object with the rendered HTML and metadata. The html field contains a complete, self-contained HTML document ready to embed.
{
"html": "<!DOCTYPE html><html lang=\"en\">...</html>",
"meta": {
"theme": "modern",
"fieldCount": 3,
"fieldTypes": ["text", "email", "textarea"],
"title": "Contact Us"
}
}
Use FormForge from any language. Here are ready-to-use examples for JavaScript and Python.
const response = await fetch("https://formforge-api.vercel.app/api/json-to-form", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer ff_live_your_key_here", }, body: JSON.stringify({ title: "Contact Us", fields: [ { name: "name", type: "text", label: "Full Name", required: true }, { name: "email", type: "email", label: "Email", required: true }, { name: "message", type: "textarea", label: "Message" }, ], }), }); const { html, meta } = await response.json(); console.log(`Form generated: ${meta.fieldCount} fields, ${meta.theme} theme`); // Render in an iframe document.getElementById("form-container").srcdoc = html; // Or inject directly // document.getElementById("form-container").innerHTML = html;
import requests response = requests.post( "https://formforge-api.vercel.app/api/json-to-form", json={ "title": "Contact Us", "fields": [ {"name": "name", "type": "text", "label": "Full Name", "required": True}, {"name": "email", "type": "email", "label": "Email", "required": True}, {"name": "message", "type": "textarea", "label": "Message"}, ], }, headers={"Authorization": "Bearer ff_live_your_key_here"}, ) data = response.json() print(f"Form generated: {data['meta']['fieldCount']} fields") # Save to file with open("form.html", "w") as f: f.write(data["html"])
# JavaScript / TypeScript npm install formforge-sdk # Python pip install formforge
FormForge includes three built-in themes. Add a theme property to your JSON to select one:
modern (default) — Clean, minimal design with emerald green accent. Best for most use cases.corporate — Professional blue theme with tighter border radius. Ideal for B2B and enterprise apps.playful — Rounded corners, purple accent, friendly feel. Great for consumer-facing products.{
"title": "Event Registration",
"theme": "playful",
"fields": [
{ "name": "name", "type": "text", "label": "Your Name", "required": true },
{ "name": "email", "type": "email", "label": "Email", "required": true },
{ "name": "role", "type": "select", "label": "Your Role", "options": ["Developer", "Designer", "PM"] }
]
}
The generated CSS is embedded in the HTML, so there are no external dependencies regardless of which theme you choose.
FormForge generates client-side validation automatically based on field properties. You can control validation through these properties:
required: true — Field must be filled before submissionminLength / maxLength — Character limits for text and textarea fieldsmin / max — Value bounds for number and date fieldspattern — Custom regex pattern for text fieldsBuilt-in format validation runs automatically for email, url, and tel field types.
{
"fields": [
{
"name": "username",
"type": "text",
"label": "Username",
"required": true,
"minLength": 3,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$",
"helpText": "Letters, numbers, and underscores only"
},
{
"name": "age",
"type": "number",
"label": "Age",
"min": 18,
"max": 120
}
]
}
Validation errors appear inline below each field with clear messages. Error regions use aria-live for screen reader support.
The HTML returned by FormForge is a complete, self-contained document. You have several options for embedding it:
The simplest approach. Set the srcdoc attribute to the returned HTML:
<iframe srcdoc="<!DOCTYPE html>...your FormForge HTML..." title="Contact form" style="width:100%;height:500px;border:none;" ></iframe>
If you want the form to be part of your page DOM (for CSS inheritance or event handling):
const response = await fetch("/api/json-to-form", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(formSchema), }); const { html } = await response.json(); document.getElementById("form-container").innerHTML = html;
submitUrl property to your schema to have the form automatically POST responses to your backend. The generated form handles loading states, success, and error messages.
If something goes wrong, check these common issues first.
| Status | Meaning | How to Fix |
|---|---|---|
| 401 | Unauthorized | Your API key is missing or invalid. Check that your Authorization: Bearer header includes a valid ff_live_ key. |
| 429 | Too Many Requests | You've exceeded your daily rate limit (20 forms/day on free tier). Wait for the reset or upgrade your plan. |
| 400 | Bad Request | Check your request body. Ensure you're sending valid JSON with a "fields" array where each field has name, type, and label. |