Folia
API

Embedding a form

The hosted link, the iframe embed, and how the embed sizes itself on your site.

Every published form has two public URLs. Both are shown in the builder's Share panel with copy buttons; this page explains what they do so you can wire them into any site builder.

The hosted page

https://www.foliaplanner.com/f/{token}

A standalone page with the form and nothing else. Link to it from a button, an email signature, or a social bio. It is marked noindex so search engines do not list it. Unpublishing or archiving the form makes this URL show “This form isn't available” — the token never changes, so re-publishing brings the same link back.

The embed

https://www.foliaplanner.com/f/{token}/embed

The same form with no page chrome, meant to be framed. It is served with Content-Security-Policy: frame-ancestors *, so it can be embedded on any origin. The Share panel gives you this snippet:

<iframe id="folia-form-1a2b3c4d" src="https://www.foliaplanner.com/f/{token}/embed" title="Inquiry form" style="width:100%;border:0;min-height:480px" loading="lazy"></iframe>
<script>
  window.addEventListener("message", function (e) {
    if (e.origin !== "https://www.foliaplanner.com" || !e.data || e.data.type !== "folia:form:height") return;
    var f = document.getElementById("folia-form-1a2b3c4d");
    if (f && e.data.formId === "{formId}") f.style.height = e.data.height + 32 + "px";
  });
</script>

Paste it into a code / HTML / embed block. Squarespace, Wix, Showit, WordPress, and Webflow all have one. No styling is needed; the frame is full-width and grows to fit.

How the height works

The embed measures itself and posts a message to the parent page whenever its height changes — as answers are typed, when validation messages appear, and on the thank-you screen:

{ "type": "folia:form:height", "formId": "…", "height": 812 }

The snippet listens for that message, checks it came from Folia and from this form, and sets the iframe's height. If you already have a message listener or a site-wide script, you can fold those three checks into it. If you skip the script entirely the form still works; it just sits in a fixed-height frame with its own scrollbar.

Redirects from inside the frame

If the form has a redirect URL, the embed navigates the top window there after a successful submit — the visitor leaves the page with your form on it and lands on your thank-you page. Without a redirect, the thank-you message shows inside the frame.

Bot protection

The embed includes Cloudflare Turnstile in its invisible mode; visitors see nothing unless Cloudflare needs a click. There is nothing to configure on your side.

Rendering the form yourself

If you would rather render the form in your own markup, GET /public/forms/{token} returns the published questions and copy, and POST /public/forms/{token}/submissions accepts answers keyed by question id. Intake forms walks through it, and the Public forms reference has every field. The server validates every answer regardless of what your page checks, so client-side validation is for the visitor's benefit, not a requirement.