Knowledge Base

Quick answers to questions about building, sharing, and managing forms.

Getting Started

How do I create my first form?+

Sign up for a free account, then click "New Form" on your dashboard. You can start from a blank canvas, pick from 500+ pre-built templates, or duplicate one of your existing forms. Add elements from the sidebar, then click Share to send it out.

What's the difference between Free and Pro?+

Free covers everything you need to run a form: unlimited forms, unlimited submissions, all 44 element types, conditional logic, and email notifications. Pro ($99/month) removes Fantastic Forms branding, raises file upload limits, unlocks the Address Autocomplete and Voice Recording elements, and gives you API access + webhooks + MCP.

Are there really no submission limits on the Free plan?+

Correct. Free plans include unlimited forms and unlimited submissions. We don't paywall the basics like other form builders do.

Building Forms

What element types are available?+

44 element types, grouped by purpose.

Text & input

  • Short Text, Long Text, Email, Phone, URL, Number (single or range)
  • Full Name (split into first/last), Address, Employer
  • Fill in the Blanks - inline cloze-style inputs in a paragraph

Choice & selection

  • Single Choice, Multiple Choice, Checkboxes, Dropdown, Yes/No
  • Cascading Dropdown - up to 4 chained dropdowns (built-in Country→State→City + Industry & Vehicle presets, or define your own)
  • Ranked List - drag to reorder a list
  • Matrix - grid of rows × columns for multi-question Likert scales

Ratings & scales

  • Star Rating, Linear Scale
  • Net Promoter Score (NPS) - standard 0–10 recommend-likelihood scale with customizable anchor labels

Date, time & scheduling

  • Date (single or range), Time, Date + Time
  • Countdown Timer - visible deadline on the form
  • Scheduler - embed Calendly / SavvyCal / Cal.com / zcal directly inside the form

Media, files & signatures

  • File Upload - per-element type/size limits + image aspect-ratio & min/max-dimension rules
  • Signature - draw or upload (PNG, 1 MB cap)
  • Voice Recording (Pro)
  • Audio Embed - auto-resolves Spotify, Apple Music, SoundCloud, Audiomack, Mixcloud, Bandcamp, YouTube, or any raw iframe snippet into a native player
  • Map - let respondents pin a location

Payments, legal & validation

  • Payment - Stripe, PayPal, Paddle, Polar, Creem, Dodo, Lemon Squeezy, Whop. Fixed or variable amount, with coupon codes.
  • Clickwrap - opt-in to your terms with timestamp & IP capture
  • Captcha

Calculations & code

  • Dynamic Calculator - live arithmetic on other fields (price * quantity, ternaries, conditional totals), with optional chart output
  • Code Block - syntax-highlighted code answers (50+ languages)
  • Social Media - collect handles for X, Instagram, LinkedIn, GitHub, TikTok, YouTube, Threads, Snapchat, etc.
  • Hidden - invisible field for URL-param / API-injected values (great for attribution)

Layout & content blocks

  • Heading, Paragraph, Statement, Divider
  • Image, Video (YouTube, Vimeo, Rumble)
How do I add conditional logic?+

Open any non-content element's settings panel and click "Add Logic". You can show/hide elements based on previous answers using if/then rules. For example, only show "How can we improve?" if the rating is 3 stars or below.

Can I split my form across multiple pages?+

Yes. Click "Add Page" at the bottom of the canvas. You'll get a Next button between pages and a progress bar at the top of the public form.

How do I customize the look?+

Open Settings (gear icon in the top toolbar) to change theme colors, fonts, and the "Submit" button label. Pro users can also remove the Fantastic Forms attribution at the bottom.

How does the Date Range option work?+

Edit any Date element, toggle "Range" on, and the form will display two date inputs separated by "to". Once both dates are filled, the total day count appears below ("3 days" for May 7 → May 9, inclusive).

Conditional Logic

What is conditional logic and when should I use it?+

Conditional logic lets you show or hide individual elements based on what the respondent has typed or selected earlier in the form. Use it to skip irrelevant questions ("only show shipping address if delivery = yes"), drill into specifics ("show 1-star feedback box only if rating ≤ 2"), or branch entire flows ("show enterprise contact info only if company size > 50"). Forms that adapt to the respondent finish faster and convert better.

How do I add a logic rule?+

Select any non-content element in the FormBuilder canvas, then click "Add Logic" in the right-hand settings panel. A rule needs three things: a source field, an operator, and (for most operators) a value to compare against. The default action is Show; flip it to Hide if you want the inverse.

Which operators are supported?+

We support 11 operators covering every common use case:

  • Equals / Does not equal - exact string or value match.
  • Contains / Does not contain - case-insensitive substring search.
  • Greater than / Less than - numeric comparisons (works on number, rating, and linear-scale fields).
  • Is empty / Is not empty - checks whether the respondent answered the field at all.
  • Is selected - for checkbox arrays, fires when a specific option is checked.
  • Matches regex / Does not match regex - full JavaScript-style RegExp for advanced patterns like ^\d{5}$ (US ZIP) or @yourcompany\.com$ (only company emails).

Invalid regex patterns are caught in the builder with a red border and an "Invalid regex" caption - they fail-closed at runtime, so a typo never breaks the form.

Can I combine multiple conditions in one rule?+

Yes. Each rule lets you add as many conditions as you need and choose between "ALL conditions must match" (logical AND) or "ANY condition can match" (logical OR). Mix them to express things like "show this field if (rating ≤ 2 AND email is provided) OR (free-text contains 'bug')".

Can I stack multiple rules on the same element?+

Yes - each element can have any number of rules. They evaluate in order, and the last rule that matches wins. Use this for tiered logic ("show by default; hide on small screens; force-show for admins").

Does conditional logic run on the server or in the browser?+

Conditional logic is evaluated entirely client-side in the respondent's browser as they fill out the form. There's no server round-trip, so visibility updates are instant. The logic rules themselves are stored as JSON on the form element and travel with the form via export/import.

Will hidden fields still be required?+

No. Once an element is hidden by logic, its "required" flag is suppressed and its value is dropped from the submission. This prevents the classic bug where a respondent gets stuck on a required field they can't see.

Is conditional logic free?+

Yes. Unlike Tally and Typeform, we don't paywall logic. Every rule, every operator (including regex) is available on the Free plan with no per-form or per-rule cap.

A/B Testing

What is whole-form A/B testing?+

A/B testing lets you run two versions (Variant A and Variant B) of the same form simultaneously, with traffic split 50/50. Each respondent gets a sticky variant assignment, so refreshing the page or returning later shows them the same version. When you've collected enough data, "Promote to Live" copies the winning variant's content back to the parent form and archives the loser.

How do I start an experiment?+

Open any form, click the A/B Test button in the toolbar, and Start Experiment. Behind the scenes we:

  1. Duplicate the form into Variant A (your original, untouched) and Variant B (your free space to change anything - question wording, element order, theme, even structure).
  2. Mark the parent form as an "experiment container" - its public URL stays the same, but it now sticky-routes 50% of visitors to A and 50% to B.
  3. Start tracking views, submissions, and conversion rate for each variant independently.

Edit Variant B until you're happy with the alternative. The original Variant A remains your safe baseline.

How is the winner decided?+

On the Experiment dashboard we show side-by-side conversion rates plus a one-tailed statistical-significance calculation (90% / 95% / 99% confidence bands). A variant is considered the winner once we reach the 95% confidence threshold AND have at least 100 sessions per variant - both bars need to clear for the "Promote" button to recommend a clear pick. Below that threshold, the dashboard shows "still gathering data" so you don't promote off random noise.

What does "Promote to Live" do?+

Promoting copies the winning variant's content (elements, settings, theme, logic, integrations) over the parent form, ends the experiment, and archives the losing variant for your records. The parent form keeps its public URL, so any embeds, share links, or marketing campaigns continue to work - only the underlying content changes.

Are visitors sticky-routed?+

Yes. The first time a respondent loads the form, we set a localStorage key scoped to the form ID (something like ffabvariant_<formId>) and pin them to either A or B. Refreshing, returning later, or hitting Back-then-Forward all show the same variant. This is critical for honest A/B results - you can't measure variant performance if respondents bounce between versions mid-session.

Can I A/B test individual fields instead of the whole form?+

No - we deliberately scrapped element-level A/B testing in favor of whole-form testing. Element-level splits inflate measurement noise (you can't cleanly attribute conversion to one element when everything around it stays the same) and bury creators in micro-experiments. Whole-form testing forces you to articulate a hypothesis ("a shorter intro + reordered fields will lift conversion") and measure the user-visible outcome.

Is A/B testing free?+

A/B testing is a Pro feature ($99/month). Free users see the A/B Test button in the toolbar but it's gated with an upgrade prompt. This is one of the few features where Pro plans differ meaningfully - the math behind statistical significance is non-trivial to ship for free.

How much traffic do I need to run a meaningful test?+

Practical rule: aim for at least 100 completed submissions per variant before declaring a winner. Below that, the variance is too high and our significance calculation will keep telling you "still gathering data". On a form getting 5 submissions/day, that's ~40 days of data; on one getting 50/day, it's 4. If your form is too low-traffic to wait that long, the honest answer is that A/B testing isn't the right tool - focus on qualitative feedback first.

Can I stop an experiment without promoting a variant?+

Yes - there's a "Cancel experiment" button on the A/B dashboard. It deletes Variant B, returns the parent form to its pre-experiment state, and resets all sticky-variant assignments so the next visitor sees the canonical form.

Fonts

How do I change my form's font?+

Open Settings (gear icon in the builder toolbar) → Font Choice. Pick any of the 35 fonts below. The change applies to all headings and body text in your form, and you'll see a live preview while typing.

Which fonts are available?+

All 35 fonts are loaded from Google Fonts and available on every plan. Click a font to see its name in its own typeface:

Inter
Archivo
Barlow
Bitter
Cabin
Crimson Text
DM Sans
Fira Sans
IBM Plex Sans
IBM Plex Serif
Josefin Sans
Karla
Lato
Libre Baskerville
Lora
Manrope
Merriweather
Montserrat
Mulish
Nunito
Open Sans
Oswald
Outfit
Playfair Display
Plus Jakarta Sans
Poppins
PT Sans
Quicksand
Raleway
Roboto
Rubik
Sora
Source Sans 3
Space Grotesk
Work Sans
Will my chosen font load fast for respondents?+

Yes. Fonts are served from Google Fonts' global CDN with the font-display: swap strategy, so the form renders instantly with a system fallback and swaps in your chosen font as soon as it downloads. No layout shift, no blank screen.

Languages

How do I translate my form?+

Open Settings (gear icon in the builder toolbar) → Language. Pick from the 70 languages below. Built-in UI strings (Submit / Next / Previous / Submitting / "This field is required" / file-upload prompts / signature labels / fallback Thank You / "made with Fantastic Forms" branding) all translate instantly. Right-to-left layout is auto-applied for Arabic, Hebrew, Persian, and Urdu.

Are my question labels and Thank You message translated too?+

No. Those stay owner-controlled. We don't auto-translate the content of your form because machine translation often misses your brand voice and important wording. If you want a multi-language form, the best pattern is to duplicate the form once per language and translate your labels manually. The built-in UI strings (buttons, validation messages) translate automatically based on your Language setting either way.

Which languages are available?+

All 70 languages are available on every plan. The native name is shown first, with the English name in parentheses:

English
Español(Spanish)
Français(French)
Deutsch(German)
Italiano(Italian)
Português(Portuguese)
Shqip(Albanian)
Nederlands(Dutch)
Svenska(Swedish)
Norsk(Norwegian)
Dansk(Danish)
Suomi(Finnish)
Íslenska(Icelandic)
Polski(Polish)
Čeština(Czech)
Slovenčina(Slovak)
Magyar(Hungarian)
Română(Romanian)
Български(Bulgarian)
Ελληνικά(Greek)
Hrvatski(Croatian)
Српски(Serbian)
Slovenščina(Slovenian)
Македонски(Macedonian)
Lietuvių(Lithuanian)
Latviešu(Latvian)
Eesti(Estonian)
Русский(Russian)
Українська(Ukrainian)
Беларуская(Belarusian)
Türkçe(Turkish)
Azərbaycanca(Azerbaijani)
Қазақша(Kazakh)
Кыргызча(Kyrgyz)
Oʻzbekcha(Uzbek)
Հայերեն(Armenian)
ქართული(Georgian)
العربية(Arabic)RTL
עברית(Hebrew)RTL
فارسی(Persian)RTL
اردو(Urdu)RTL
हिन्दी(Hindi)
नेपाली(Nepali)
বাংলা(Bengali)
தமிழ்(Tamil)
తెలుగు(Telugu)
മലയാളം(Malayalam)
मराठी(Marathi)
ગુજરાતી(Gujarati)
ਪੰਜਾਬੀ(Punjabi)
ไทย(Thai)
Tiếng Việt(Vietnamese)
Bahasa Indonesia(Indonesian)
Bahasa Melayu(Malay)
Filipino
日本語(Japanese)
한국어(Korean)
简体中文(Chinese (Simplified))
繁體中文(Chinese (Traditional))
粵語(Cantonese)
Kiswahili(Swahili)
Afrikaans
isiZulu(Zulu)
አማርኛ(Amharic)
Català(Catalan)
Euskara(Basque)
Galego(Galician)
Malti(Maltese)
Cymraeg(Welsh)
Gaeilge(Irish)

Sharing & Embedding

How do I share a form?+

Click the Share button in the top toolbar. You'll get a public link, a QR code, and three embed snippets: inline, popup, and full page. The popup snippet is now a single <script> tag, so you can paste it anywhere on your site.

How do popup embeds work?+

In Share → Popup, choose the trigger style (button, link, side tab, or auto-open after delay), button text, color, and position. Copy the one-line <script> snippet and paste it before </body> on your site. The popup builds itself when the page loads.

Can I track form submissions in Google Analytics or Meta Pixel?+

Yes. Open the form, go to Settings → Attribution Tags, toggle it on, then paste any combination of provider IDs. We fire conversion events to whichever providers you enable, both on the hosted page and on every embed.

Events we fire on submit:

  • Meta Pixel → `Lead`
  • Google Analytics 4 / gtag → `form_submission`
  • TikTok Pixel → `SubmitForm`
  • OpenAI Pixel → `lead_created`
  • LinkedIn Insight → conversion event tied to the partner ID
  • Microsoft Clarity → session recording continues automatically; the submit is captured as part of the visitor session.
Which attribution providers are supported?+

Out of the box:

  • Meta (Facebook) Pixel - conversion tracking for Facebook & Instagram ad campaigns.
  • Google Analytics 4 (gtag.js) - traffic, events, conversion goals.
  • Google Tag Manager - paste a container ID and orchestrate any tag inside GTM.
  • TikTok Pixel - conversion tracking for TikTok ad campaigns.
  • OpenAI Pixel - ChatGPT Ads conversion attribution (fires `lead_created` on submit).
  • LinkedIn Insight Tag - B2B conversion tracking and retargeting.
  • Microsoft Clarity - free session recordings + field-level heatmaps.

You can enable as many as you want per form. IDs are stored per-form so different forms can route to different ad accounts or workspaces.

How do I set up Microsoft Clarity on my forms?+

Create a free project at clarity.microsoft.com, copy your Clarity Project ID (10-character code from the install snippet), then open Settings → Attribution Tags on the form and paste it into the "Microsoft Clarity Project ID" field. Clarity will start recording sessions and field-level heatmaps on the very next form view - no extra script needed.

Where can I find each provider's tracking ID?+

Quick lookup table:

  • Meta Pixel ID - Meta Events Manager → Data Sources → your pixel. 15-16 digit number.
  • GA4 Measurement ID - Google Analytics → Admin → Data Streams → Web. Starts with `G-`.
  • Google Tag Manager - GTM dashboard, top-right of your container. Starts with `GTM-`.
  • TikTok Pixel ID - TikTok Ads Manager → Assets → Events → Web Events. ~20 alphanumeric characters.
  • OpenAI Pixel ID - ChatGPT Ads Manager → Tools → Conversions → Pixel. Format `oai-px-XXXXXXXXXX`.
  • LinkedIn Partner ID - LinkedIn Campaign Manager → Account Assets → Insight Tag. 6-7 digits.
  • Microsoft Clarity Project ID - clarity.microsoft.com → Settings → Setup. 10-character alphanumeric code.
Do attribution tags work inside embedded forms?+

Yes. The inline, popup, and full-page embed scripts all load the configured pixels on the parent page, so events are attributed to the visitor's real domain (not ours). That means your existing audiences, conversion campaigns, and Clarity recordings keep working - no extra setup on your site.

Submissions & Analytics

Where do I find responses?+

Click any form in your dashboard, then "Submissions" in the top nav. You'll see a sortable list, plus aggregate stats: total views, total submissions, completion rate, and average completion time.

What is Kiosk Mode and how do I use it?+

What it is. Kiosk Mode (Pro) turns any published form into a self-driving station for an unattended tablet or laptop. Ideal for trade-show booths, in-store surveys, clinic intake devices, and restaurant feedback iPads.

How to enable. Open your form, click Settings, scroll to "Kiosk Mode", toggle it on.

How to launch. Open the Share modal, click the "Kiosk" tab, and either scan the QR code with the tablet or copy the URL. Bookmark it or add to the home screen for one-tap launch. The URL is your normal form URL with ?kiosk=1 appended.

What you get.

  • Auto-restart after each submission (configurable 1-60 seconds)
  • Idle timeout that resets mid-form if a respondent walks away, with a warning 10 seconds before reset
  • Customizable exit PIN (4-6 digits) so customers cannot leave the kiosk without staff intervention
  • Customizable exit button label (defaults to EXIT)
  • Fullscreen lock on first tap
  • Hidden "Powered by" footer
  • Blocked right-click and dev-tools hotkeys
  • Ability to email the kiosk link and QR code to whoever will run the tablet
What is Form Versioning and how do I use it?+

What it is. Form Versioning (Pro) keeps a full snapshot of your form every time you save. Roll back if you break something, review who changed what, or diff two versions side by side.

How to access it. Open any form in the builder and click the History button in the top bar (next to Settings). A slide-in panel appears on the right listing every saved version.

What each version shows.

  • Version number and when it was saved
  • Who saved it (name and email)
  • A short change summary (for example, "3 fields added, 1 removed; settings updated")
  • Badges for special versions: Current, Restored, or Auto-snapshot

How to restore a version. Click Restore on any version in the list. Your current working state is automatically saved as a new version first, so a restore is always reversible. If you restore by mistake, just open History again and restore the pre-restore snapshot.

How to compare two versions. Select two versions using the checkboxes, then click Compare. The panel shows a side-by-side diff highlighting fields that were added (green), removed (red), modified (amber), or reordered. Modified fields can be expanded to see the exact before and after JSON.

Retention and limits.

  • Only structural changes create a version (title-only edits without other changes do not clutter the list)
  • The most recent 50 versions are kept per form; older versions are pruned automatically
  • Every version stores a full snapshot so restoration always works, even for the oldest kept version
How do I export submissions?+

There are three places to export from the Submissions page, and all three offer the same file formats.

Export All. Top-right of the Submissions page. Downloads every response for the form in a single file.

Bulk Export. Appears once you check one or more rows. Downloads only the selected rows, packaged as a zip with one file per submission. The exception is Parquet, which ships as one canonical file spanning the whole selection.

Single-response Export. Open a submission by clicking the eye icon in the Actions column. On the same row as Tags you will see an Export button that downloads exactly that one response.

See the next question for what each file format is best used for.

What file formats can I export to?+

CSV (.csv). Universal spreadsheet format. Opens in Excel, Google Sheets, or Numbers. Best for pivot tables, quick sorting, and analyst-friendly work.

Excel (.xlsx). Native Microsoft Excel format with typed cells, preserved dates, and column widths. Best when the recipient specifically asked for an Excel file.

JSON (.json). Structured tree of every submission. Best for developers, Zapier or Make webhook debugging, and pushing responses into a custom app.

Word (.docx). Formatted document with question labels and respondent answers. Best for reviewing a small batch in Microsoft Word, adding comments, or printing.

PDF (.pdf). Printable single-file report, one submission per page with a checkmark header. Best for archiving, sharing with a non-technical stakeholder, or attaching to an email.

Plain text (.txt). Human-readable text file with no formatting. Best for a quick low-friction dump you can paste into an email or ticket.

Markdown (.md). GitHub-flavoured markdown. Best when the destination is GitHub Issues, Notion, Linear, Obsidian, or any dev-oriented doc tool.

XML (.xml). Legacy enterprise format with slugified element names. Best when a downstream CRM, ERP, or gov portal explicitly requires XML.

Parquet (.parquet). Columnar binary file, snappy-compressed. Best for data-team pipelines. Pipes straight into Snowflake, BigQuery, DuckDB, or Databricks without conversion.

How do I get notified of new submissions?+

Settings → Notifications → toggle "Email me on new submissions". You'll get a clean HTML summary at the email address on your account.

Can I see analytics by country/device?+

Yes. The Submissions page shows IP, country, city, browser, OS, device type, and screen resolution for every response. Useful for catching bot traffic and seeing where your audience is coming from.

Pro Plan Features

What unlocks with Pro?+

Removal of Fantastic Forms branding, larger file uploads, the Voice Recording element, the Address Autocomplete element, the Public REST API v1, outbound Webhooks, custom roles & permissions, and priority support.

How do I upgrade?+

Settings → Billing → Upgrade, or click "Upgrade" anywhere a Pro feature is gated. Payment is handled by Stripe; you'll be billed $99/month and can cancel anytime.

Do you offer refunds?+

Yes! We can facilitate a full refund of your last month's payment upon request (post cancellation.)

ID Verification

What is the ID Verification element?+

A Pro-only field that asks the respondent to verify their real-world identity by uploading a government-issued photo ID (passport, driver's licence, national ID) and matching it against a live selfie with liveness detection (the verifier blinks/smiles/turns head to prove they're a real human, not a photo). The check is powered by an enterprise KYC engine used by banks and fintechs.

When should I use it?+

Any form where you can't afford anonymous or fraudulent submissions: tenant applications, contractor onboarding, age-gated content, financial intake forms, restricted ticketing, healthcare patient registration, marketplace seller verification, high-value giveaways. If "is this person real" is part of your decision, ID Verification turns your form into a screening tool.

How do I add it to a form?+

In your form editor, click "Add New Element" → ID Verification. Drag it into the page where you want the check. The respondent will see an embedded panel that walks them through document scan → selfie → liveness → result. Submission only proceeds when the verification status flips to "Approved".

What's checked exactly?+

Three checks run in sequence - all three must pass:

  • Document authenticity - OCR, hologram detection, MRZ checksum, and template-database matching against thousands of ID types worldwide.
  • Face match - selfie compared to the photo on the document with a confidence score.
  • Liveness - short video challenge proving the selfie is a real person in front of the camera, not a printed photo or video replay.
What do I do when a verification fails?+

Your form has a per-form setting (Form Settings → Verification) with two options: Block submission (the default - submission button is disabled if verification didn't pass) and Flag & allow (submission goes through but is tagged "verification_failed" in your Submissions inbox for manual review). Pick "Flag & allow" if you want to gather the data anyway and triage later.

What data do I see for verified submissions?+

Inside the submission row you get: verification status (Approved / Declined / Expired), document type (e.g. "Passport · USA"), the redacted document number, full name extracted from the document, date of birth, and a confidence score. The raw document image stays inside the verification provider's system per privacy regulations - we never store it.

Is the document image stored?+

No. Fantastic Forms never stores the document image or selfie. Both are processed by the verification provider and discarded per their retention policy. We only persist the verification metadata listed above.

Which countries and ID types are supported?+

230+ countries and territories, including all G20 nations. Document coverage includes passports, national identity cards, driver's licences, residence permits, and selected military/government IDs. The supported-documents list is updated continuously by the verification provider.

What does it cost me?+

Nothing extra on top of your Pro plan if you use our default verification workflow - the per-check fee is absorbed in the $99/month price. If you want to bring your own verification account (custom branding, your own retention policy, your own dashboard), enter your API key in Settings → Integrations → ID Verification and we'll route through your account instead.

Is it WCAG / accessibility friendly?+

The verification panel is WCAG 2.1 AA. The liveness challenge has a "skip motion" mode for respondents with vestibular disorders, and document upload supports keyboard-only navigation and screen-reader announcements at every step.

Can it be triggered conditionally?+

Yes. Use the conditional-logic engine to show the ID Verification element only when certain answers are given (e.g. "Are you applying as a contractor? → Yes" → reveal verification). This keeps the friction off most respondents while still gating the high-stakes path.

Proof of Funds

What is the Proof of Funds element?+

A form field that lets your respondent connect a US bank account in real time and prove they have at least a minimum balance you specify. The connection is read-only (we never see the login credentials, never move money, never store the account number).

When should I use it?+

Any form where "does this applicant actually have the money?" is part of your decision:

  • Rental & lease applications - verify the prospect has 3x rent in reserves before scheduling a viewing.
  • Loan pre-qualification - auto-screen out applicants without a bank balance threshold.
  • High-ticket service intake - confirm a deposit before a sales call.
  • Pre-IPO secondary deals, asset finance, fractional ownership - gate on accredited-investor proof.
  • Anti-fraud screening - combine with ID Verification to gate sweepstakes / giveaways against bots.
How do I add it to a form?+

In your form editor, open "Add Element" → SecurityProof of Funds. Drop it into the page where you want the check. In the right-hand settings panel set the Minimum balance required (e.g. $5,000) and the On failure behavior - either `Flag for review` (submission goes through, tagged as below-threshold) or `Block submission` (the Submit button stays disabled). Leave the threshold empty if you only need to confirm "this is a real bank account with a positive balance".

What does the respondent experience look like?+

A single button on your form labelled "Connect your bank to verify funds". Clicking it opens a secure hosted bank-login modal where the respondent searches for their bank, signs in with their normal online-banking credentials (handled entirely by the verification provider, not by us, not on your domain), and selects which accounts to share. The whole flow typically takes 20-30 seconds. We then immediately read the balance and show a green "Funds verified" or amber "Below the requested threshold" indicator before they hit Submit.

What data do I see for verified submissions?+

Inside the submission row you get: the verification status (`verified` / `insufficient` / `failed`), the verified balance amount and currency, the bank name(s), and the last 4 digits of the account number(s) the respondent connected. The respondent's identity, login, and full account number are never exposed - the verification provider holds those server-side.

Is the bank login or account number stored?+

No. The bank-connection session is read-only and short-lived: the respondent's login credentials are entered on the verification provider's domain and never reach Fantastic Forms. We store only the aggregated balance result and the last 4 digits of the connected account, both of which are necessary for the form owner to act on the submission and audit the trail.

How fast is the balance check?+

Real-time. The verification provider pushes the latest balance from the bank on session completion, and we read it within ~2 seconds of the respondent closing the bank-login modal. There is no overnight batch or delayed verification - the form owner sees the result before the respondent even hits Submit.

Which banks are supported?+

Approximately 5,000 US financial institutions, including all major retail banks (Chase, Bank of America, Wells Fargo, Citi, Capital One, USAA, etc.), most regional banks, and the largest credit unions. Smaller community banks and some niche credit unions may not be supported. The supported list expands continuously. If a respondent's bank is not supported they'll see a search "no results" state inside the bank-login modal - your form can then route them to a manual upload using conditional logic.

What does it cost?+

The first 750 verifications per workspace per month are included on the Pro plan. Each verification beyond that bills $1 to your Stripe-on-file as an invoice item that rolls into your next monthly invoice. 750/month covers ~95% of fintech / proptech / lending forms; the overage exists so power users with seasonal spikes never get rate-limited mid-funnel.

Can it be triggered conditionally?+

Yes. Use the conditional-logic engine to show the Proof of Funds element only when certain answers are given (e.g. "How much are you looking to put down? → > $50,000" → reveal Proof of Funds). This keeps low-value respondents friction-free while reserving the expensive verification call for high-stakes paths.

Will it work for non-US respondents?+

Not currently. The underlying bank-connection network is US-only - non-US respondents will see "no results" when they search for their bank. If you have a meaningful international audience we recommend (a) using conditional logic to skip the element for non-US country selections, or (b) reaching out so we can prioritise an open-banking integration for your region.

Integrations

Which apps can I connect Fantastic Forms to?+

We ship 62 native integrations across CRM, project management, marketing, automation, databases, messaging, support, analytics, call tracking, scheduling, webinars, and accounting - plus 8 payment processors and 5 tracking pixels. Each one is configured per-form with your own credentials - no shared bottleneck, no middleware layer:

ActiveCampaign

Sync submitters as contacts.

Airtable

Append a record per submission.

Apollo

Push contacts into outreach sequences.

Asana

Create a task in any project.

Attio

Upsert People records by email.

Brevo

Add submitters to a contact list.

Cal.com

Embed a Cal.com booking page.

Calendly

Embed Calendly with prefill.

CallRail

Send leads with UTM/gclid attribution.

CallTrackingMetrics

Upsert contacts with full attribution.

Circle

Invite submitters into a Space.

ClickMeeting

Register attendees to a ClickMeeting room.

ClickUp

Create a task in any list.

Close

Create a Close lead per submission.

Coda

Append rows to any Coda table.

Copper CRM

Create a Copper person per submission.

Discord

Rich embed to any channel.

Drip

Add subscribers with tags.

Flodesk

Add subscribers to a segment.

Folk

Push contacts into Folk groups.

Follow Up Boss

Create real-estate CRM people.

Ghost

Create newsletter members.

GoHighLevel

Push contacts to sub-accounts.

Google Sheets

Auto-append every submission.

HubSpot

Upsert Contacts deduped by email.

IFTTT

Fire an IFTTT applet on every submission.

Intercom

Upsert Contacts (US/EU/AU).

Kit

Attach submitters to a Kit form.

Klaviyo

Upsert profiles, attach to list, fire flows.

Less Annoying CRM

Create LACRM contacts with notes.

Livestorm

Register attendees on a Livestorm event.

Mailchimp

Add submitters to an Audience.

Make

Trigger any Make scenario.

Microsoft Teams

Adaptive Card to any channel.

Mixpanel

Track submissions as events.

n8n

Trigger any n8n workflow.

Notion

Create a row in any database.

Nutshell

Create a Nutshell lead with contact.

Omnisend

Upsert subscribed contacts.

Ontraport

Create Ontraport contacts.

Pipedrive

Create or update Pipedrive People.

SavvyCal

Embed your SavvyCal page.

Segment

Forward to all your destinations.

Slack

Block Kit message to any channel.

Smartsheet

Append rows to a Smartsheet sheet.

SmartSuite

Create a record per submission.

Stackby

Append rows to any Stackby table.

Telegram

Bot message to any chat or channel.

Trello

Create a card on any list.

WebinarJam

Auto-register attendees to WebinarJam / EverWebinar.

WebinarNinja

Register attendees to a WebinarNinja webinar.

WhatConverts

Push form-submission leads with attribution.

Zapier

Trigger any Zap via Catch Hook.

zcal

Embed your zcal booking page.

Zendesk

Open a ticket per submission.

Zoho CRM

Upsert Leads or Contacts.

Plus 9,000+ apps reachable through the n8n, Make, Zapier, and IFTTT integrations. All four share the same JSON envelope, so a workflow you build in one platform is one-paste-away from running in another.

Payment processors - accept payments inside any form via a hosted checkout you control:

Stripe

Cards, Apple Pay, Google Pay, Link.

PayPal

PayPal balance and credit cards.

Paddle

Merchant-of-record with built-in tax.

Polar

Developer-first checkout for SaaS.

Creem

European MOR alternative to Paddle.

Dodo Payments

MOR checkout for global creators.

Lemon Squeezy

Subscription-friendly digital storefront.

Whop

Creator-economy checkout for digital products.

Tracking pixels & analytics - auto-injected on your published form (or hosted on your own domain) to attribute conversions back to your ad campaigns:

Meta Pixel

Facebook & Instagram Ads conversions.

Google Tag (gtag.js)

GA4 + Google Ads conversion events.

LinkedIn Insight Tag

B2B retargeting & conversion tracking.

Microsoft Clarity

Free heatmaps & session recordings.

TikTok Pixel

TikTok Ads conversions and lead capture.

Where do I configure an integration?+

Each integration has its own page at /integrations/{name}, accessible from the Integrations directory in the sidebar of any signed-in account. You bring your own credentials (API token, webhook URL, etc.), paste them once per form, and we save them securely on that form's settings.

Do integrations run in real-time or on a delay?+

Real-time. Every integration fires as a fire-and-forget background task the moment a submission lands, typically delivered within 1 to 3 seconds. If the destination service is down, the submission is still saved to Fantastic Forms and we log the failure on the form so you can retry.

Is the same submission sent to all connected integrations?+

Yes. If you connect a single form to, say, Google Sheets + Slack + HubSpot + Zapier, every new submission triggers all four in parallel. Each integration is independent, so one failing doesn't affect the others.

What's the difference between a native integration and using Zapier/Make/n8n?+

Native (Google Sheets, Slack, HubSpot, Notion, Airtable, etc.): direct, no middleware, no per-task billing, no rate limits on top of the destination's own. Best when the app is on our list.

Zapier / Make / n8n / IFTTT: use these for the long tail of 9,000+ other apps, or when you need branching logic between Fantastic Forms and the destination. You bring your own automation account; we just POST the submission JSON to your webhook.

Can I send the same submission to multiple Slack channels (or multiple sheets)?+

Per-form, each native integration takes one destination (one channel, one sheet, one database). For fan-out, the simplest pattern is to connect a Zapier/Make/n8n workflow that splits to multiple targets.

Developers

How do I get an API key?+

Pro users: Settings → API → Generate Key. Treat it like a password; it grants full access to your forms and submissions. The same key works for our REST API, MCP server, and signed webhook payloads.

Where are the API docs?+

Visit /developer (or click "Developer" from your Settings menu). You'll find every REST endpoint, request/response examples, a copy-pasteable MCP client config snippet, and a "Try it" panel that uses your real API key.

What is MCP and how do I connect Claude / Cursor to Fantastic Forms?+

Model Context Protocol (MCP) is an open standard that lets AI assistants - Claude Desktop, Cursor, Windsurf, Zed, and any other MCP-capable client - read and write data on services you authorize. Our MCP server lives at https://fantasticforms.com/api/mcp and exposes tools to list, read, create, and update your forms in plain language.

Example: connect Claude Desktop

Edit claude_desktop_config.json and add:

{
 "mcpServers": {
 "fantastic-forms": {
 "url": "https://fantasticforms.com/api/mcp",
 "headers": {
 "Authorization": "Bearer ff_live_YOUR_KEY"
 }
 }
 }
}

Restart Claude Desktop. Then you can ask things like "List my draft forms", "Create a 3-question customer survey with a 1-10 rating and a comment box", or "Add an email field to the contact form."

Cursor and other MCP clients use the same URL + Bearer header (settings vary; consult their MCP docs). Pro plan only.

What is the CLI and when should I use it?+

The Fantastic Forms CLI (@fantasticforms/cli) lets you manage your forms from the terminal. It's the only major form builder with a real CLI - declare your forms in YAML, commit them to git, deploy them on merge. Form-as-code, with all the review/history/blame/rollback benefits git already gives your code.

Install + log in

npm install -g @fantasticforms/cli

ff login --token ff_live_YOUR_KEY
ff whoami

Scaffold + deploy your first form

ff init # writes form.yaml
ff push form.yaml # creates the form, writes the new id back
ff push form.yaml # subsequent runs UPDATE in place
ff pull <form-id> -o form.yaml # round-trip an existing form into YAML

Validate in CI (GitHub Actions example)

- run: npm install -g @fantasticforms/cli
- run: ff validate forms/*.yaml

Other commands: ff list, ff submissions list/export, ff webhook test <url>. Full reference at /cli.

Best for: agencies managing many forms across clients, teams that want forms in their git workflow, anyone who wants to validate form schemas in CI before they hit production. Pro plan only.

How do webhooks work?+

In any form's Settings → Integrations → Webhooks, paste a URL. Every new submission posts to that URL as a JSON body within seconds. Includes a signature header (HMAC-SHA256) you can verify with your webhook secret. Failed deliveries are retried with exponential backoff.

When should I use the REST API vs. MCP vs. CLI vs. Webhooks?+

REST API - pull data on demand from any backend (Node, Python, PHP, Go, etc.). Best for syncing forms or submissions into your own product or running scheduled reports.

MCP - give an AI assistant conversational read/write access to your forms. Best for "build me a form" / "fix this question" workflows inside Claude, Cursor, or other AI clients.

CLI - manage forms from the terminal as YAML files. Best for form-as-code workflows: agencies, teams that want forms in their git repo, anyone validating schemas in CI.

Webhooks - react in real-time to incoming submissions. Best for plugging Fantastic Forms into your own server-side automation without polling.

Payments

Which payment providers can I use?+

Fantastic Forms supports 8 hosted-checkout providers: Stripe, PayPal, Paddle, Polar, Creem, Dodo Payments, Lemon Squeezy, and Whop. Pick one per Payment element - your buyer is redirected to that provider's secure checkout and returned to a Thank-you page with their order receipt after a successful payment.

How do I add a Payment element?+

Open your form in the builder → Add Element → Input Fields → Payment. In the right panel choose the provider, pricing mode (Fixed / Variable / Suggested), currency, product name, and (for non-Stripe providers) the product or variant ID from your provider dashboard.

Where do I paste my API keys?+

Open the form → Settings → Payment Provider Credentials → click your provider card → paste the key(s) → click "Test connection" to confirm the key is valid before publishing. Keys are stored on that specific form only.

Can I accept Klarna, Affirm, Apple Pay, Google Pay, or Cash App Pay?+

Yes - and you don't need any extra setup in Fantastic Forms. These run on top of your existing Stripe payment provider:

  • In your Stripe Dashboard, open Settings → Payments → Payment methods.
  • Toggle on Klarna, Affirm, Cash App Pay, Apple Pay, Google Pay, or any other regional methods you want to offer.
  • Stripe Checkout (what your Fantastic Forms Payment elements use) automatically surfaces each method based on the customer's currency, country, and device - for example, Apple Pay shows up on Safari/iOS, Google Pay on Chrome/Android, Klarna for buyers in supported regions, etc.

The form-builder doesn't need any code or setting changes. Once enabled in Stripe, the next checkout that meets the eligibility rules will offer the new method on the payment page.

What's the difference between Fixed, Variable, and Suggested pricing?+

Fixed = one set price (e.g. $29.99). Variable = the buyer enters any amount between your min/max (good for tipping or "name-your-price"). Suggested = same as variable but with suggested-amount chips (e.g. $5 / $10 / $25 / $50) plus a free input below - great for donations, tips, or pay-what-you-want pricing.

What happens if a buyer abandons checkout?+

No submission is recorded. Pending payment rows are auto-deleted after 30 minutes - your analytics and exports only contain successfully completed transactions. This is the "block" behavior the form-builder is designed around.

How are refunds and disputes tracked?+

When a refund or chargeback is initiated in your provider dashboard, our webhook receiver flips the matching submission to status "refunded" or "disputed". The Submissions table shows a colored badge (Paid / Refunded / Disputed) and you can filter by status. Open the submission to see a payment timeline (paid → disputed → resolved → refunded) with exact timestamps.

Does Stripe have a "platform key" I can use without configuring my own?+

No. Every provider - including Stripe - requires you to paste your own Secret Key. That guarantees payments land in YOUR account, not someone else's. Get the key from dashboard.stripe.com → Developers → API Keys (use sktest… for testing, sklive… for production).

Why does PayPal need both a Client ID and Secret?+

PayPal uses OAuth 2.0 client_credentials - Client ID identifies your app and Secret authenticates it. Both come from developer.paypal.com → My Apps & Credentials → REST API apps. Toggle "Use sandbox" on while testing.

Paddle / Polar / Creem / Dodo / Lemon Squeezy - what extra info do they need?+

Each requires an API key plus a product/variant identifier you create in their dashboard: Paddle = Price ID (pri…), Polar = Product ID (optional - leave blank for ad-hoc pricing), Creem = Product ID, Dodo = Product ID (pdt…), Lemon Squeezy = Store ID + Variant ID. The credentials card in Settings shows where to find each one.

Does it work with multi-currency?+

Yes - pick from 17 majors (USD, EUR, GBP, CAD, AUD, JPY, CHF, SEK, NOK, DKK, NZD, SGD, HKD, BRL, MXN, INR, ZAR) per Payment element. The Pay button label updates live with the correct currency symbol and amount.

How do I configure webhooks at the provider end?+

In each provider's dashboard, add a webhook endpoint pointing to https://YOUR-DOMAIN/api/payments/webhooks/{provider} - e.g. /api/payments/webhooks/stripe. Subscribe to `checkout.session.completed`, `charge.refunded`, `charge.dispute.created`, `charge.dispute.closed` (or each provider's equivalent event names - refunds & disputes are auto-detected on the generic webhook endpoint).

Are there fees?+

Fantastic Forms charges no extra payment fees - you only pay what your chosen provider charges (typically 2.9% + $0.30 per successful transaction). All providers above offer test/sandbox modes you can use without real money.

Team Roles & Seats

What are the four team roles, and what can each do?+

Fantastic Forms uses four built-in roles, scoped to a workspace:

  • Owner - Full control. There is exactly one owner per workspace. Only the owner can transfer ownership, delete the workspace, manage billing, and change the workspace plan. Owners also have every Admin/Editor/Viewer permission.
  • Admin - Can invite, remove, and change the roles of other members (except the owner). Admins can create, edit, archive, and delete forms; configure integrations; view all submissions and analytics; and edit workspace settings. They cannot manage billing or delete the workspace itself.
  • Editor - Can create new forms, edit existing ones, and view submissions on any form in the workspace. Editors cannot invite teammates, configure billing, or change workspace settings.
  • Viewer - Read-only access. Can open forms in the builder (without saving) and view submissions and analytics. Useful for clients, stakeholders, or compliance reviewers who need visibility without edit rights.

Roles are assigned at invite time and can be changed any time by an Owner or Admin from Teams → Member → Change role.

How many team members can I have?+

Free plan - 1 seat (you). Team collaboration is a Pro feature; the "Invite Member" button is disabled on free accounts.

Pro plan ($99/month) - 10 seats included, counting the owner. That means the owner + 9 invited teammates can all collaborate without extra cost.

Need more than 10? Each additional seat is $10/month, billed as a separate line item on your Stripe subscription. There is no upper limit and no enterprise upcharge - just $10 per extra seat, every month, for as many as you need.

How does extra-seat pricing work exactly?+

When you invite an 11th teammate on the Pro plan, the app pops up an "Add an extra seat?" confirmation modal explaining the $10/month charge. Clicking Confirm:

  1. Adds a new "Fantastic Forms - Extra Seat" line item to your existing Stripe subscription with quantity 1.
  2. Stripe immediately creates a prorated invoice for the partial month (e.g., if you're 12 days into a 30-day cycle, you'll be charged $6 for the rest of this month).
  3. The invitation is then created and the new teammate receives their invite email.

Every subsequent extra seat increments the same line item by 1 with the same proration behavior. You can review every extra-seat invoice item in your Stripe portal under Billing → Invoices.

What happens to billing when I remove a member or cancel an invitation?+

Removing a member or cancelling a pending invitation is prorated immediately:

  1. The seat is freed.
  2. If the new used-seat count is below your included 10, the corresponding extra-seat line item on your Stripe subscription is decremented by 1.
  3. Stripe issues a prorated credit back to you for the unused portion of that month, applied automatically to your next invoice.

Example: if you remove a seat halfway through the month, you get roughly $5 credited toward next month's bill. You will never be charged for a seat you no longer use.

Do pending invitations count toward my seat limit?+

Yes - by design. A pending invitation is a held seat. If your workspace has 6 members and 4 pending invites, you're using 10 seats and the next invite will trigger the extra-seat purchase flow. This prevents the edge case where someone fires off 50 invites, fills their workspace, then "downgrades" before the recipients accept.

If you decide an invitation is no longer needed, cancel it from Teams → Pending Invitations → Cancel. That frees the seat (and prorates a credit if it was an extra seat).

How do I invite a teammate?+
  1. Navigate to Teams in the sidebar (you must be Owner or Admin).
  2. Click Add Member.
  3. Enter their email and pick their role (Admin / Editor / Viewer).
  4. Click Add Member.

If they already have a Fantastic Forms account, they're added to the workspace immediately and receive a notification email. If they don't have an account yet, they get a one-click sign-up email and will appear in your team once they finish signing up.

How do I change someone's role or remove them?+

On the Teams page, find the member row and click the role badge or the three-dot menu:

Change role - pick a new role from the dropdown. Takes effect immediately.

Remove from workspace - confirms and removes them. They lose all access immediately. Their forms remain in the workspace (forms belong to the workspace, not to individual users).

Owners cannot have their role changed by anyone else and can't be removed (you have to transfer ownership first, then remove).

Can I transfer ownership to someone else?+

Yes. As the current Owner, go to Teams → find the member you want to make Owner → menu → "Transfer ownership". This requires confirming your password. After transfer, you become an Admin on the same workspace, and the new Owner takes over billing and workspace-deletion rights.

This is the right move if you're leaving the company and want to hand off the account to a colleague without disrupting the team or losing the subscription.

Do extra seats give the same Pro features?+

Yes - every teammate gets the full Pro feature set: removed Fantastic Forms branding, 5 MB file uploads, custom domains, priority support, all 62 native integrations, advanced analytics, A/B testing, and conditional logic. There is no "seat tier" downgrade for extra seats. You pay $10/month and they get the full Pro experience.

Where can I see my current seat usage and extras?+

Teams page → the card header reads `"X of Y seats used · 10 included + N extra ($N0/mo)"`. You can also call `GET /api/billing/seats` from your API key to get the same data programmatically - useful for triggering billing alerts in your own monitoring (e.g., notify yourself when seat usage hits 9/10).

Enterprise SSO (OIDC)

What is Enterprise SSO on Fantastic Forms?+

Enterprise SSO lets your team log in to Fantastic Forms with your company's existing identity provider (IdP) instead of a Fantastic Forms password. It uses the OpenID Connect (OIDC) standard, so it works with Okta, Azure Active Directory / Entra ID, Google Workspace, Auth0, OneLogin, and any other OIDC-compliant IdP. When a teammate hits Log In, they enter their work email, click "Continue with SSO", get bounced to your IdP's login page, and land back in Fantastic Forms already signed in. No separate password to remember, no shared credentials, no orphan accounts when someone leaves the company.

How do I set it up?+
  1. In Fantastic Forms, go to Settings → SSO. Copy the Redirect URI shown at the top of the panel (e.g. `https://fantasticforms.com/api/sso/callback`).
  2. In your IdP admin console, create a new OIDC application. Paste the Redirect URI as the allowed redirect URL. Copy the Issuer URL, Client ID, and Client Secret the IdP gives you back.
  3. Back in Fantastic Forms, paste all three into the SSO panel, set your Allowed email domain (e.g. `acmecorp.com`), and click Test issuer reachability to confirm your Issuer URL resolves cleanly.
  4. Flip the Enable SSO for this workspace toggle and hit Save.

That's it. Any teammate on `@acmecorp.com` will now see "Continue with SSO" work on the login page.

Where do I find the Issuer URL, Client ID, and Client Secret in my IdP?+

Okta. Admin dashboard → Applications → your OIDC app → General tab. Issuer URL is your Okta domain (org auth server) or `<domain>/oauth2/<authserverid>` (custom auth server). Client ID + Secret are on the same page.

Azure AD / Entra ID. Portal → App registrations → your app → Overview. Issuer URL is under Endpoints as the OpenID Connect metadata URL (minus the `/.well-known/...` suffix). Client ID is on Overview. Client Secret is under Certificates & secrets → Client secrets.

Google Workspace. Google Cloud Console → APIs & Services → Credentials → OAuth 2.0 Client IDs. Issuer URL is `https://accounts.google.com`. Client ID + Secret are on the credential detail page.

Auth0. Dashboard → Applications → your app → Settings. Issuer URL is `https://<your-tenant>.auth0.com/`. Client ID + Secret are on the same page.

OneLogin. Admin → Applications → your OIDC app → SSO tab. Click the "Well-known Configuration" link and copy the `issuer` field for Issuer URL. Client ID + Secret are on the same tab.

What does "Allowed email domain" do?+

This is how we know which workspace's SSO config to use when a teammate clicks "Continue with SSO". They enter their work email, we split off the domain (`alice@acmecorp.com` → `acmecorp.com`), find the workspace whose Allowed email domain matches, and route them to that workspace's IdP. If two workspaces both claimed the same domain we'd have ambiguity, so the domain is workspace-scoped and unique in practice. Pick your primary company domain.

What happens the first time a new teammate logs in via SSO?+

We JIT-provision them. On successful callback we check whether `(Issuer URL, sub)` already maps to a user. if not, we create a fresh user row with `sso_managed = true`, mark their email as verified (the IdP already did that), attach them to the workspace whose SSO config they came through, and grant them the workspace's Pro plan. No manual "invite" step needed. anyone whose email domain matches your Allowed email domain can log in and get seated automatically. If you want tighter control, set the Allowed email domain to a more specific subdomain (e.g. `contractors.acme.com` vs `acme.com`).

Is the Client Secret safe to enter here?+

Yes. we encrypt the Client Secret at rest with Fernet (symmetric AES-GCM) before writing to Postgres. Once saved, the raw value is never returned to any API. the Settings UI only sees a `clientsecretpresent: true` flag. If you rotate the secret in your IdP, just paste the new value into the same field and click Save; the old encrypted value is overwritten. If you clear the field and save, the existing secret is preserved (blank = keep-current, not delete).

What if my IdP is unreachable or I fat-fingered the Issuer URL?+

The Settings panel has a Test issuer reachability button that hits `<Issuer>/.well-known/openid-configuration` and reports success or failure before you save. If save-time discovery fails, the whole save is blocked so you can't lock your team out. If it fails after you've been running successfully (e.g. IdP outage), users get a clear "Identity provider is unreachable" 502 error and can either wait it out or fall back to the password login form on the same page.

Which OIDC scopes and claims do you request?+

We request the standard `openid email profile` scopes. From the ID token we consume `sub`, `email`, and `name` / `preferred_username`. Group / role claims are ignored on this MVP. every SSO user lands as a full Pro member of the workspace. If you need group-to-role mapping ("engineers → Editor, finance → Viewer"), let us know. that's a natural next step and only needs a small mapping table in the SSO settings panel.

How does the login flow work end-to-end?+
  1. User visits `/login`, types their work email, clicks Continue with SSO.
  2. Browser hits `GET /api/sso/authorize?email=alice@acme.com`. Backend looks up the workspace by domain, generates a random `state` + `nonce`, persists them in `ssologinstates`, and 302-redirects to the IdP's authorization endpoint with those params.
  3. User authenticates in the IdP.
  4. IdP redirects back to `GET /api/sso/callback?code=…&state=…`. Backend validates state (single-use, expires in 10 min), exchanges the code for an ID token at the IdP's token endpoint, and verifies the token's signature against the IdP's JWKS (with `iss` / `aud` / `exp` / `nonce` all enforced).
  5. Backend upserts the user, mints a Fantastic Forms JWT, and 302-redirects the browser to `/sso/success#token=<jwt>`. The token stays in the URL fragment so it never hits our logs.
  6. `/sso/success` yanks the token, stashes it in `localStorage`, and hard-navigates to `/dashboard`. Done.
Do you support SAML too?+

Not on this release. SAML is doable but more complex to integrate cleanly (XML signatures, per-IdP quirks, ACS URL config). If your IdP supports both OIDC and SAML. and virtually every modern IdP does. OIDC is the recommended path anyway. If you're on a legacy SAML-only stack, let us know and we'll prioritise a SAML add-on.

Can I disable SSO temporarily without deleting my config?+

Yes. Flip the Enable SSO for this workspace toggle off and click Save. The Issuer URL / Client ID / Client Secret stay stored but the "Continue with SSO" button will no longer resolve to your IdP. Any users who were previously SSO-managed can still log in with a password (as long as they have one). we don't force-lock them out.

SCIM 2.0 Directory Sync

What is SCIM?+

SCIM (System for Cross-domain Identity Management, RFC 7643 / 7644) is the standard protocol IdPs use to push user lifecycle events into third-party apps. In practice: when your IT team creates a new employee in Okta / Azure AD / OneLogin, that employee automatically appears in Fantastic Forms with the right access. When someone leaves the company and gets deactivated in the IdP, they lose Fantastic Forms access within seconds. No manual "remove seat" step, no forgotten stale accounts. It's the difference between "we integrated with SSO" and "we're fully compliant with our IT deprovisioning policy." Enterprise buyers ask for this.

How is SCIM different from SSO?+

They solve adjacent but different problems:

  • SSO (OIDC). controls login. When a user opens Fantastic Forms, they authenticate against your IdP instead of a Fantastic Forms password. Login-only, always initiated by the user.
  • SCIM. controls provisioning. Your IdP pushes user data into Fantastic Forms proactively: creates, updates, and (crucially) deactivates users based on what your HRIS / IT team does. Doesn't touch login. it just manages which accounts exist.

Most enterprises use both together. SSO alone leaves you with stale accounts after employees leave; SCIM alone means a user has to log in once via password before their IdP-managed account is useful.

How do I set up SCIM?+
  1. In Fantastic Forms, go to Settings → SSO. Scroll to the SCIM 2.0 Directory Provisioning card.
  2. Click Generate SCIM token. A `scim_…` token appears. copy it now, it will never be shown again.
  3. Copy the SCIM Base URL shown above the token (e.g. `https://fantasticforms.com/api/scim/v2`).
  4. In your IdP admin console, open the Fantastic Forms app you already set up for SSO and enable its SCIM connector. Paste the Base URL as the SCIM endpoint and the token as the bearer credential.
  5. Save. Your IdP will hit our `/ServiceProviderConfig` endpoint to verify the connection, then start pushing users on the schedule you configured (usually immediate).
Which SCIM operations do you support?+

The full RFC 7644 core spec for the User resource:

  • `GET /ServiceProviderConfig`. capabilities advertisement
  • `GET /ResourceTypes`, `/Schemas`. schema discovery
  • `POST /Users`. create user (idempotent. duplicate emails return the existing record instead of erroring, which matches what Okta/Azure expect on retries)
  • `GET /Users?filter=userName eq "…"`. search by email
  • `GET /Users/{id}`. read a single user
  • `PUT /Users/{id}`. full replace
  • `PATCH /Users/{id}`. partial update (the RFC 7644 §3.5.2 `Operations` array shape that Okta/Azure send)
  • `DELETE /Users/{id}`. soft-deactivate (see next question)

Group resource is not implemented on this MVP release. All the common IdP deprovisioning flows work with User endpoints alone.

What happens when the IdP deactivates or deletes a user?+

We soft-deactivate rather than hard-delete. When Okta sends `PATCH {"active": false}` or `DELETE /Users/{id}`, we flip the user's `active` column to `false` and stamp `deprovisioned_at` with the current timestamp. The row stays in our database so their historical form submissions stay properly attributed (nobody wants an audit trail full of "deleted user" placeholders). But they cannot log in anymore. every auth path checks the `active` flag. If the IdP later reactivates them (e.g. they rejoined the company), `PATCH {"active": true}` immediately restores access with no data loss.

What does the `PATCH /Users/{id}` op actually accept?+

The `Operations` array supports `add`, `replace`, and `remove` operations against these paths (case-insensitive):

  • `active`. toggle the login flag
  • `userName`. change email address
  • `displayName`. change full name
  • `name.formatted`. same as displayName
  • No `path` at all. with `value` as an object, we set any of the above keys found

Any other paths are silently ignored so the IdP's optional attributes (`title`, `preferredLanguage`, phone numbers, etc.) don't cause failures. We prefer permissive over strict here. a rejected PATCH is what causes IdPs to spam you with retry errors.

Is the SCIM token safe to share with my IdP?+

Yes. SCIM tokens are workspace-scoped bearer tokens with no other access. Specifically: (a) they can't log in as any user, (b) they can't read anything outside your workspace, (c) they're stored only as a sha256 hash (like `api_keys`), and (d) the raw value is shown to you exactly once when generated. If you accidentally leak one, hit Rotate token in the SCIM card. the old value is instantly revoked and a fresh one is minted. Rotation is a good habit every 6–12 months even without a leak.

How do I test that provisioning actually works?+

Two ways:

  1. From your IdP. Okta has a "Test Connection" button in the Provisioning tab; Azure AD has "Provision on demand". Both hit our `/ServiceProviderConfig` endpoint and confirm the token works. If that passes, run a test-user assignment and watch that user appear in your Fantastic Forms Teams page within a minute.
  2. With curl. from a terminal you can hit the endpoint directly. Replace `<TOKEN>` and try:
curl -H "Authorization: Bearer <TOKEN>" \
 https://fantasticforms.com/api/scim/v2/ServiceProviderConfig

A 200 with a JSON blob describing capabilities means auth is wired up correctly.

What if the token gets compromised or an employee with access leaves?+

Immediately hit Rotate token in the SCIM card. This one operation atomically (a) revokes the current token (any subsequent SCIM request with the old token returns 401), and (b) generates a new one. Paste the new value into your IdP. Your provisioning downtime is however long it takes you to copy-paste one string. usually under a minute.

Which IdPs have you tested against?+

The endpoints are spec-compliant against RFC 7644, which means they work with any IdP that implements SCIM 2.0 correctly:

  • Okta. Universal Directory → SCIM app template → paste Base URL + token. Full Create / Update / Deactivate cycle verified.
  • Azure AD / Entra ID. Enterprise apps → your app → Provisioning tab → Automatic mode. Uses `PATCH` shapes we handle.
  • OneLogin. App → Provisioning tab. Standard SCIM 2.0 connector.
  • Google Workspace. SCIM support is limited on their side (Google prefers Directory API); use OIDC SSO alone in that case.
  • Auth0. Auth0 doesn't emit SCIM as a source. its SCIM is inbound (i.e. it consumes SCIM from other IdPs). So if you're using Auth0 as your IdP, provisioning still happens via OIDC JIT on first login.
How does this affect my seat / billing count?+

Auto-provisioned SCIM users count exactly the same as manually-invited teammates. If you have Pro (10 seats included) and SCIM pushes an 11th user, we charge you the $10/month extra seat automatically, prorated for the rest of the month. If SCIM later deactivates that user, the seat is freed and you get a prorated credit against next month. This works because SCIM operations run through the same Stripe-subscription logic as manual invites. no separate accounting.

Can I turn SCIM off but keep SSO?+

Yes, and they're independent. Hit Revoke in the SCIM card and provisioning stops immediately; your OIDC SSO login continues to work unchanged. To re-enable later, click Generate SCIM token and paste the new value in your IdP. Existing users' active status doesn't change when SCIM is turned off. we only stop receiving new lifecycle events.

Are SCIM operations captured in the audit log?+

Yes. every provisioning action lands in your Audit Logs with the `source: "scim"` tag, so a SOC2 auditor can see exactly what your IdP did and when:

  • `user.scim.created`. brand-new user provisioned by the IdP
  • `user.scim.updated`. IdP re-POSTed / renamed an existing user (retry-safe)
  • `user.scim.deactivated`. `PATCH active:false` from the IdP (Slack-alerted)
  • `user.scim.reactivated`. `PATCH active:true` from the IdP
  • `user.scim.deleted`. explicit `DELETE /Users/{id}` from the IdP (soft-delete under the hood; Slack-alerted)

Additionally, SSO/SCIM admin actions are logged too: `sso.config.updated`, `sso.login`, `scim.token.issued`, `scim.token.rotated`, `scim.token.revoked`. Token events are Slack-alerted since a rogue admin issuing a SCIM token is a supply-chain risk. Filter for any of these in `/admin/audit-log` to get a complete provisioning timeline you can hand to your compliance team.

IP Allowlisting

What is IP Allowlisting on Fantastic Forms?+

IP Allowlisting restricts dashboard access for your workspace to a fixed set of IP addresses or CIDR ranges. When enabled, anyone who tries to log in OR whose active session is validated from an IP that is not on the allowlist gets a 403 with your custom denial message. It is a common SOC 2 / HIPAA control for teams that require admins to be on corporate VPN or an office network before they can touch forms, submissions, or billing.

How do I set it up?+
  1. Go to Settings → IP Allowlist. The panel auto-detects your current public IP and shows it at the top.
  2. Click Add to list to prefill your current IP as `<your-ip>/32`. Add any additional office / VPN egress IPs, one per line. CIDR ranges (`10.0.0.0/24`, `2001:db8::/32`) are supported.
  3. Optionally set a Custom blocked-access message shown to anyone we block (max 500 chars). Common examples: "Please connect via corporate VPN" or "Contact IT@acme.com to be added."
  4. Flip the Enforce allowlist toggle. The toggle stays disabled until your current IP is in the list, so you cannot accidentally lock yourself out.
  5. Click Save. From this moment on, any login attempt or session refresh from an unlisted IP will be blocked.
What exactly is gated? Do respondents get blocked from submitting my forms?+

No. IP Allowlisting only gates dashboard access (login + session validation). Public form submissions, password reset flows, and file uploads are intentionally NOT affected. If your marketing form is at `fantasticforms.com/f/abcd`, a respondent in Tokyo will still be able to fill it out and submit even if your allowlist only permits your San Francisco office IP for admin login. This keeps the customer-facing surface working while locking down the admin side.

Does it support IPv6 and CIDR notation?+

Yes to both. Every entry runs through the standard `ipaddress` library, which handles single IPs (`203.0.113.7` normalises to `/32`), IPv4 CIDR (`10.0.0.0/24`), and IPv6 CIDR (`2001:db8::/32`). We normalise on save, so pasting `10.0.0.5/24` from a firewall rule becomes `10.0.0.0/24` in the stored list.

What happens if all entries are invalid, or if I try to enable an empty allowlist?+

Invalid entries (typos, malformed strings) are rejected on save with a "Rejected invalid entries: ..." warning, but valid entries are still accepted. If you try to enable enforcement with zero valid entries, the API refuses with a 400 explaining you need at least one entry. this is intentional to prevent a self-inflicted lockout. If enforcement is enabled and every listed IP happens to be unparseable, the service denies all requests (fail-closed for misconfiguration) rather than silently letting everyone through.

Are blocked attempts logged?+

Yes. Every blocked login or session refresh writes a `security.ipallowlist.blocked` entry to the Audit Log with the source IP, the context (`login` vs `session`), and the affected workspace. Every allowlist edit writes `security.ipallowlist.updated`. This gives your compliance team a full paper trail of who tried to get in from where.

Can platform downtime lock me out of my own product?+

No. Enforcement is written fail-open on lookup errors: if we cannot read your workspace settings for any reason, we let the request through rather than lock every admin out of their own dashboard. This is a deliberate availability vs security trade-off. Successful logins are still recorded so you can spot anomalies after the fact.

I got locked out. How do I recover?+

Ask any other Owner of the workspace to log in from an allowed IP and disable enforcement (or add your current IP) in Settings > IP Allowlist. If you are the sole Owner and truly stuck, contact Fantastic Forms support with proof of ownership. we can clear the allowlist from the backend as a break-glass recovery.

Malware Scanning

What is the Malware Scanner on Fantastic Forms?+

The Malware Scanner is a Pro feature that inspects every file uploaded through your forms against 70+ commercial antivirus engines (Kaspersky, Microsoft Defender, ESET, Bitdefender, Sophos, and more). If any engine flags the file as malicious, the upload is rejected at the API layer with an HTTP 400 before the file ever lands in your storage. The respondent sees a clear "This file appears to contain malware" message and the rejection is written to your Audit Log for compliance.

How do I turn it on?+

Nothing to install, no API keys to manage. Just go to Settings > Malware Scanner, flip the Enforce malware scanning on uploads toggle, and click Save. Every subsequent upload to any form in this workspace is scanned before storage. It's off by default so you only spend scan quota on forms that actually need the protection.

Does it slow down uploads?+

For known-clean files: negligible. The scanner first checks a fingerprint of the file against a global reputation database (~200ms round trip), which returns instantly if the file has been seen before. Only if the fingerprint is unknown do we submit the full file for a fresh analysis (up to 25 seconds). This "fingerprint first, deep-scan second" flow keeps the fast path fast: for a typical office running a hiring form, 99% of PDFs and images will resolve via fingerprint alone. If the fresh scan takes longer than 25 seconds we fail-open and let the file through with a warning in the Audit Log. Never leave a respondent hanging.

What is the scanning quota, and what happens if it's exceeded?+

Fantastic Forms provides a generous shared free-tier quota across the platform, with automatic failover to a secondary scanning provider if the primary is exhausted. The two providers use completely different engines and risk-flag rulesets, so hitting one limit doesn't block the other. In practice you get thousands of free scans per month. If both providers are exhausted, the scanner fails open with a `scan skipped` entry in the Audit Log so nothing is silently unprotected. Heavy-volume workspaces can contact support to raise the tier.

What file types are scanned?+

Every file uploaded through the `/api/files/upload` endpoint is eligible, regardless of type (PDFs, Office docs, ZIPs, images, video, audio, etc.). Voice recordings and signature captures skip scanning entirely since they are generated on the client and never contain foreign bytes.

Where does the scanned file go? Is my customers' data private?+

For most forms (contact forms, job applications, invoice attachments) the standard scanning tier is a great trade-off. Files are analysed by the scanning network and results are aggregated across the security community. If you handle strictly regulated data (patient records, defence, financial statements with PII) leave scanning off for those specific forms and rely on your own DLP tooling upstream. If you need a private scanning tier scoped to your workspace, contact support. We can enable a paid private tier that keeps uploads confidential.

What happens when a file is detected as malicious?+

The API returns HTTP 400 with a plain-English message the FormView shows the respondent verbatim: "This file appears to contain malware and was rejected by our security scanner (N of M antivirus engines flagged it). Please upload a different, clean file." Nothing is written to your storage, no submission row is created, and an audit log entry `security.malware.rejected` is emitted with the file fingerprint, the number of engines that flagged it, and the first 5 engine names. Enough forensic detail for your security team without leaking the malicious bytes.

Can I test that scanning is working without downloading real malware?+

Yes. The safest way is to upload the EICAR test file, a 68-byte string universally recognised by antivirus engines as a benign test signature. Every engine in the scanning network has it in its database, so your first fingerprint lookup will return "malicious" and Fantastic Forms will reject the upload immediately. This gives you a fully deterministic end-to-end proof that scanning is live without ever touching real malware.

What if the scanning network is down?+

The scanner fails-open by design: the upload is allowed and an entry is written to your Audit Log with a `verdict` describing why (e.g. `scanner error: ConnectError`). This keeps your product working during third-party outages. Owners can filter the Audit Log by `security.malware.*` action to spot silent bypasses. If you would prefer fail-closed behaviour for regulated workloads, contact support. It is a two-line code change we can enable per-workspace.

Audit Logs

What are Audit Logs?+

Audit Logs are an immutable, time-stamped trail of every state-changing action that happens inside your workspace. They give Owners and Admins a complete record of who did what and when, which is invaluable for security investigations, compliance reporting (SOC 2, GDPR, HIPAA-style controls), and simply answering "wait, who changed that?" without guessing.

Every entry captures the actor (user email + ID), the action (e.g. `form.updated`, `member.invited`, `apikey.revoked`), the target object, a structured `meta` payload with the relevant before/after context, and a UTC timestamp. Logs cannot be edited or deleted from the UI; they age out only via your retention policy.

What actions get logged?+

The backend interceptor records every state change across the platform. The main categories:

  • Forms: created, updated, archived, restored, deleted, published, unpublished, backup created/restored.
  • Submissions: deleted, exported (CSV/PDF/JSON), tagged, untagged.
  • Team & seats: member invited, invitation cancelled, role changed, member removed, ownership transferred, extra seat added/removed.
  • Billing: plan upgraded, plan downgraded, payment method updated, subscription cancelled.
  • Integrations: connected, disconnected, credentials rotated.
  • API & developer: API key created, revoked, rotated; webhook created, updated, deleted; MCP token generated.
  • Security & account: login, login failure, password changed, 2FA enabled/disabled, account deletion requested.
  • Workspace settings: name changed, branding updated, retention policy changed, Slack webhook updated.

Read-only actions (viewing a form, opening Analytics) are intentionally not logged to keep the trail focused and the volume sane.

How long are audit logs retained?+

Default retention is 90 days. Workspace owners on the Pro plan can adjust this from Teams > Audit Log > Retention (days), with a number input that accepts any value from 1 to 365 days.

At the configured retention boundary, older entries are automatically purged. If you need long-term archival beyond 365 days (for compliance audits, for example), export to CSV on a schedule and store the file in your own system of record.

Who can view audit logs?+

Audit Logs are a Pro-only feature. On a Pro workspace:

  • Owners: full read access to the workspace-wide audit log plus the retention setting and Slack webhook configuration.
  • Admins: full read access to the workspace-wide audit log. They cannot change retention or the Slack webhook.
  • Editors and Viewers: no access. The Audit Logs panel is hidden from their view.

On the Free plan, the Audit Log card shows an "Upgrade to Pro" CTA instead of the log. Events are not recorded while on the Free plan; logging begins the moment the workspace upgrades to Pro.

Can I export audit logs?+

Yes. From the Audit Logs page, click Export CSV in the top-right. The export respects any filters you have active (date range, actor, action type, target), so you can pull a focused slice rather than the entire trail.

For programmatic access, the same data is available through `GET /api/audit-logs` with the same filter query parameters. Authenticate with your API key (Owner or Admin scope required). Pagination is cursor-based and the response is JSON; ideal for piping into a SIEM or your own data warehouse.

How do Slack notifications for critical events work?+

Owners can paste a Slack Incoming Webhook URL into Settings > Audit Logs > Slack Webhook. Once saved, a curated list of critical actions is fanned out to that Slack channel in near real time:

  • Ownership transferred
  • Member removed
  • 2FA disabled on the owner account
  • API key revoked or rotated
  • Subscription cancelled
  • Workspace deletion requested

Each Slack message includes the actor, the action, a deep link back to the relevant audit log entry, and the UTC timestamp. If the webhook fails (channel deleted, URL revoked), the audit log still saves the entry normally; only the Slack fan-out is skipped.

Non-critical actions (form edits, submission exports, role changes between non-owner roles) are intentionally not pushed to Slack to avoid noise. They are still queryable inside the in-app Audit Logs view.

How do I find a specific event?+

The Audit Logs page has three composable filters at the top:

  1. Date range: pick a preset (Last 24 hours, Last 7 days, Last 30 days) or a custom start/end date.
  2. Actor: filter to a specific teammate by email.
  3. Action: filter to a specific event type (e.g. `form.deleted`).

Clicking any row expands the entry to show the full `meta` payload (before/after diff for updates, the deleted record snapshot for deletes, etc.). Use the Copy event ID button if you need to reference the entry in a support ticket.

Per-user activity timeline+

From Teams > [Member], the Activity panel renders that user's most recent actions inside the current workspace. Useful when you need to:

  • Verify what a teammate did during their last login.
  • Investigate a specific user before role-changing or off-boarding.
  • Pull a focused timeline for a single contractor without scrolling the full workspace log.

The panel uses the same backing data as the workspace-wide Audit Logs view, just pre-filtered to that user. Owners and Admins see this panel; Editors and Viewers do not.

Account & Security

How do I change my password?+

Settings → Profile → Change Password. You'll need your current password to confirm.

How do I enable two-factor authentication?+

Settings → Security → 2FA. Scan the QR code with any authenticator app (1Password, Authy, Google Authenticator) and confirm the 6-digit code.

How do I delete my account?+

Settings → Profile → Delete Account. This permanently removes all forms, submissions, and personal data within 30 days, per our Privacy Policy.

Are my forms and responses encrypted?+

Yes. All traffic is HTTPS-only, data at rest is encrypted with AES-256, passwords are bcrypt-hashed, and submission payloads use TLS 1.2+ in transit. We are GDPR and CCPA compliant.

Troubleshooting

My respondents say the form won't submit+

Most often this is a required field that wasn't filled. The page should highlight which one in red. If submitters are seeing a captcha loop, try regenerating the form short link in Share. Still stuck? Use the Contact link in the footer with the form ID.

The popup embed doesn't appear on my site+

Confirm your CSP (Content Security Policy) allows scripts from fantasticforms.com and frames from the same. Most CMS hosts (WordPress, Webflow, Wix, Squarespace) work out of the box. Check the browser console for blocked-resource errors.

I'm getting too many spam submissions+

Add the Captcha element (free), usually the last element on the form. For higher-volume forms, also enable rate limiting in Settings → Spam Protection.

I still need help+
We respond to every message within one business day. Use the to reach us.