FormForge API

FormForge converts JSON form definitions into beautiful, self-contained HTML forms with built-in CSS, client-side validation, and accessible markup. The API requires no SDK — just a single POST request.

Base URL: https://formforge-api.vercel.app

Version: 1.0.0  |  Format: JSON over HTTPS

Try it free: The API allows 20 forms per day without an API key. Sign up for a free key to track usage and unlock more quota.

Authentication

Pass your API key in the Authorization header using Bearer scheme:

http
Authorization: Bearer ff_live_your_api_key_here

Alternatively, use the X-Api-Key header for legacy clients. Keys always start with ff_live_ (live) or ff_test_ (test).

Unauthenticated requests are allowed on the free anonymous tier (20 forms/day per IP).


Error Responses

All errors return a JSON object with error, code, and an optional details field.

json
{
  "error": "The 'fields' array is required.",
  "code":  "INVALID_INPUT"
}
CodeHTTPDescription
INVALID_INPUT400Bad request body or missing required field
PARSE_ERROR400Request body is not valid JSON
UNAUTHORIZED401API key missing, invalid, or inactive
RATE_LIMITED429Daily form limit exceeded for your tier
INPUT_TOO_LARGE413Request body exceeds your tier's size limit
INTERNAL_ERROR500Server-side rendering error

Rate Limits

Limits reset at midnight UTC. Authenticated requests return rate-limit headers on every response:

http
X-RateLimit-Limit:     20
X-RateLimit-Remaining: 17
X-RateLimit-Reset:     1740787200
TierForms/dayInput limitPrice
Free (anonymous)2050 KB$0
Free (keyed)2050 KB$0
Builder300512 KB$14/mo
EnterpriseUnlimited5 MB$39/mo

POST /api/json-to-form

POST /api/json-to-form
Accepts a JSON form schema and returns a complete, self-contained HTML document with embedded CSS, client-side validation, and submit handling.

Request body

FieldTypeDescription
fieldsrequiredarrayArray of field definition objects (1–100 items). See Field Schema.
titleoptionalstringForm heading displayed above the fields.
descriptionoptionalstringSubtitle text below the title.
themeoptionalstringmodern | corporate | playful | minimal. Default: modern.
submitUrloptionalstringURL to POST the form data to. If omitted, the form shows a success message on submit without making an HTTP request.
submitLabeloptionalstringLabel on the submit button. Default: Submit.
methodoptionalstringGET | POST. Default: POST.
showRequiredoptionalbooleanShow asterisk on required fields. Default: true.
stepsoptionalarrayMulti-step wizard mode. Each item has title (string) and fields (array). When provided, fields are grouped into wizard steps with Next/Previous navigation. See Multi-Step Forms.

Responses

200 Form rendered successfully
json
{
  "html": "<!DOCTYPE html>\n<html lang=\"en\">...",
  "meta": {
    "theme":      "modern",
    "fieldCount": 3,
    "fieldTypes": ["email", "text", "textarea"],
    "title":      "Contact Us",
    "generatedAt": "2026-02-28T12:00:00.000Z"
  }
}
400Invalid schema
401Invalid API key
413Request too large for tier
429Rate limit exceeded

Try it out


                

POST /api/json-to-embed

POST /api/json-to-embed
Converts a JSON form schema into a complete, self-contained HTML page with inline CSS, inline JavaScript for client-side validation, and an iframe embed snippet. Perfect for embedding forms in third-party sites, emails, or CMS pages.

Request body

FieldTypeDescription
fieldsrequiredarrayArray of field definition objects (1–100 items). See Field Schema.
titleoptionalstringForm heading displayed above the fields.
descriptionoptionalstringSubtitle text below the title.
themeoptionalstringmodern | corporate | playful | minimal. Default: modern.
actionoptionalstringURL to submit the form data to. If omitted, the form shows a success message on submit.
methodoptionalstringGET | POST. Default: POST.
optionsoptionalobjectAdditional settings: submitText (button label), successMessage, redirectUrl, honeypot (boolean, default true).

Responses

200 Embeddable form rendered successfully
json
{
  "html": "<!DOCTYPE html>\n<html lang=\"en\">...",
  "embedSnippet": "<iframe src=\"data:text/html;base64,...\" ...></iframe>",
  "meta": {
    "fieldCount":      3,
    "requiredFields":  ["name", "email"],
    "estimatedHeight": 420,
    "validationRules": 4,
    "generatedAt":     "2026-02-28T12:00:00.000Z"
  }
}
400Invalid schema
401Invalid API key
413Request too large for tier
429Rate limit exceeded

Try it out


                

POST /api/signup

POST /api/signup
Creates a new free-tier API key for the provided email address. The plain-text key is returned once and cannot be retrieved again.

Request body

FieldTypeDescription
emailrequiredstringValid email address. Maximum 3 active keys per address.

Responses

201Key created
json
{
  "message":  "API key created successfully. Save this key — it will not be shown again.",
  "api_key":  "ff_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "tier":     "free",
  "email":    "[email protected]",
  "rate_limit": {
    "forms_per_day":  20,
    "max_input_bytes": 51200
  }
}
400Invalid email
409Max keys per email reached (3)

Field Schema

Each item in the fields array supports the following properties:

PropertyTypeDescription
namerequiredstringUnique field identifier used as the HTML name attribute.
typerequiredstringField type. See Field Types.
labelrequiredstringHuman-readable label displayed above the field.
requiredbooleanIf true, the field is validated as non-empty on submit.
placeholderstringPlaceholder text inside the input (not for checkbox/radio).
helpTextstringSmall helper text shown below the field.
optionsstring[]Required for select and radio. Optional for checkbox (creates a multi-select group).
valuestringDefault/pre-filled value.
min / maxnumber|stringMin/max value for number and date fields.
minLength / maxLengthnumberCharacter limits for text and textarea.
patternstringRegex pattern for custom input validation.
disabledbooleanRenders the field in a disabled state.
readonlybooleanRenders the field as read-only.
autocompletestringHTML autocomplete hint (e.g. email, name).

Themes

The theme property controls the visual style of the generated form. All themes are self-contained CSS — no external fonts or stylesheets are loaded.

ThemeDescriptionAccent color
modernClean, minimal. System sans-serif font, 8px border radius. Good default for most products.#10b981 (emerald)
corporateProfessional blue. Tighter radius, bold labels. Suitable for B2B and SaaS dashboards.#1d4ed8 (blue)
playfulRounded, colorful. Cursive font stack, large radius, purple accent. Great for consumer apps.#8b5cf6 (violet)
minimalBorderless, spacious. Monospace labels, bottom-border-only inputs, uppercase accents. Ultra-clean aesthetic for developer tools and modern apps.#2563eb (blue)

Field Types

TypeHTML elementNotes
text<input type="text">Supports minLength, maxLength, pattern
email<input type="email">Validates email format on blur and submit
number<input type="number">Supports min, max
textarea<textarea>Resizable. Supports minLength, maxLength
select<select>Requires options array. Renders a blank placeholder option
checkbox<input type="checkbox">No options: single toggle. With options: multi-select group
radio<input type="radio">Requires options array. Single-select group
date<input type="date">Browser date picker. Supports min, max as YYYY-MM-DD strings
tel<input type="tel">Validates phone number format
url<input type="url">Validates URL format (requires https://)

Multi-Step Forms

Use the steps parameter instead of (or alongside) fields to create wizard-style multi-step forms with a progress indicator and Next/Previous navigation.

Backwards compatible: If steps is not provided, the API behaves exactly as before with a flat fields array. Maximum 20 steps, 100 total fields across all steps.

Step schema

PropertyTypeDescription
titlerequiredstringStep title shown in the progress indicator.
fieldsrequiredarrayArray of field objects for this step. Same schema as top-level fields.

Example request

json
{
  "title": "Registration",
  "theme": "modern",
  "steps": [
    {
      "title": "Personal Info",
      "fields": [
        { "name": "name", "type": "text", "label": "Full Name", "required": true },
        { "name": "dob",  "type": "date", "label": "Date of Birth" }
      ]
    },
    {
      "title": "Contact",
      "fields": [
        { "name": "email", "type": "email", "label": "Email", "required": true },
        { "name": "phone", "type": "tel",   "label": "Phone" }
      ]
    },
    {
      "title": "Preferences",
      "fields": [
        { "name": "plan",  "type": "radio", "label": "Plan", "options": ["Free", "Pro", "Team"], "required": true },
        { "name": "terms", "type": "checkbox", "label": "I agree to the Terms", "required": true }
      ]
    }
  ]
}

Behavior

  • Each step is shown one at a time with a numbered progress indicator at the top.
  • The Next button validates the current step's fields before advancing.
  • The Previous button navigates back without re-validating.
  • The Submit button only appears on the last step.
  • On successful submission, the form resets to step 1.
  • The response meta.stepCount field tells you how many steps were rendered.