Skip to content
Form builder

Lead capture that cannot drift from your data model

Every field on the form points at a field on the entity. There is no mapping screen, because there is nothing on the form that does not already exist on the record.

  • A form field is an entity field, not a copy of one
  • Two lines on your page, in a shielded area your stylesheet still reaches
  • Five outputs after a submission, each one switchable on its own
  • The intake API stays: the form you already run keeps working
desktopmobile
1Your roofFour questions, then we know whether it is worth a call.page 1 of 2
First name
short text · required
Postcode
short text · required
Roof area
number · m² · min 10
Shading
shown if roof area ≥ 80
2How to reach youThree fields · maps to first_name, email, phonecollapsed
Add page

The tools were never the problem

Somebody adds a question to the form. The record it produces now carries a field the CRM has never heard of. Nothing breaks loudly that afternoon: it breaks weeks later, when a routing rule filters on a field that is empty for everything captured since.

We ran a lead generation business on six of them. This is the part that cost us the most and showed up on no invoice.

You pay per seam
Every tool in the chain has its own subscription, and the one feature you actually needed is usually one price tier up.
A field is not one change
Add it in one place and it has to be added in the others. Miss one and nothing fails loudly: it fails the next time somebody filters on it.
Someone else's release is your outage
An API changes, a mapping stops matching, a webhook starts returning something new. You hear about it from the person who was waiting.
The builder

Three columns, and the middle one is the form

The supply on the left, the form in the middle, the properties of whatever is selected on the right. A form belongs to one entity, and every field in it writes into a field of that entity. That is the whole reason the module exists: there is no mapping screen, because there is nothing on the form that does not already exist on the record.

  • Conditions point backwards. A field can depend on answers that come before it, never on ones that come after.
  • Rows divide by share. Two fields in a row split it, rather than you setting a width in pixels.
  • The form decides how a choice looks. The same select can be a dropdown here and image tiles there, without a second field.
  • Intake or amendment. Decided when you create the form, because the two behave differently all the way down.
your-domain.com/rooftop-check
Step 1 of 2

Your roof

Four questions, then we know whether it is worth a call.

First name
Marie
Postcode
53111
Roof area in m²
128
Shadingshown because roof area ≥ 80
Partly, in the afternoon
ContinueTakes about a minute.
Two lines on your page
<script src="https://app.leadflip.net/embed.js"></script>
<div data-form="rooftop-check"></div>
Authentication
one for your own system, one for a foreign source
API keys

It travels as a header: Authorization: Bearer key_…

landing pagelast 24 Sep
old CRM, importnever used
Source tokens

It sits in the address rather than in a header: /api/v1/in/{token}

Google Ads, spring campaignappears on every record
partner form, 2025revoked
On your own page

Two lines, and your stylesheet still reaches inside

Under Embed you get an empty box and a script. The script draws the form into a shielded area, so a general rule on your page cannot move it by accident, and your own stylesheet still reaches in through fixed names. If you have no website, every form also has an address of its own that renders the same form on a plain page.

  • Colours and corners through variables. Set them on the form's box; the brand stays in your stylesheet, not stored a second time here.
  • Single parts through ::part(). Page, step, field, label, error, choices, cards, buttons, each addressable by name.
  • One page styled differently. Give a page an identifier in the builder and build on it while paging.
  • Fonts come from your website. Load the font on your page and name it; the shielded area will not fetch one itself.
After a submission

The record is created first, and the rest is a list

Five outputs sit on the right of the builder: put into a stage, send a confirmation, notify the team, start a distribution, call another system. Each one can be switched off on its own, and none of them is load-bearing. Switch them all off and you still get a record. The reverse does not hold: a full mailbox must not cost you a lead.

  • The order is a promise. Record first, then the confirmation, the automation last, so the sender's mail is out before a chain somebody built three months ago.
  • Only for booked modules. Stage and distribution belong elsewhere; unbooked, the builder does not offer the output at all.
  • A result per output. Ran, skipped or failed with a reason, on the submission itself rather than in a mailbox.
  • Files reach the record first. So a confirmation that mentions an attachment is not lying.
Log
is anything arriving from that source at all
  1. 09:41:12200landing pagerecord created
  2. 09:38:04200Google Adsduplicate, existing record updated
  3. 09:31:55422partner formpostcode is not a number
  4. 09:30:02200landing pagerecord created
Spam and numbers

No puzzle images, and no cookie either

Three measures run on every form with nothing to configure: an invisible trap field, a minimum of two seconds between the first keystroke and the submit, and a cap per minute. Alongside them the form counts itself, which is a different promise: views, forms started, submissions and the completion rate, over the last thirty days, with the step people drop out at.

  • No cookie, no address, no identifier. The counting does not set one, so it needs no banner of its own.
  • The drop-off is in the builder too. You see which step loses people while you are editing it.
  • Counting can be switched off. Per form, if you would rather your own analytics tool had it alone.
  • Which addresses may submit. A list of domains, house rules rather than a lock, and it says so.
The other way in

The intake API is not going anywhere

Most records will keep arriving from somewhere that is not our builder: an ad account, a form on a site you do not control, another system. That was true while this module was being built and it is true now. A submission becomes a record with your fields either way, and the builder is a second producer beside the API rather than its successor.

  • One endpoint, two ways in. An API key for your own system, a source token as a ready-made address for a foreign one.
  • Idempotent. A sender that posts twice produces one record.
  • Always open. Intake needs no booked module, because records belong to the core.
  • Duplicates at the door. Decided per entity, before anything else runs.
Take in a record
the main way in, always open
Request
POST /api/v1/records
Authorization: Bearer key_…

{
  "entity": "rooftop_de",
  "data": {
    "first_name": "Marie",
    "email": "m.kerner@example.de",
    "postcode": "53111",
    "roof_area": 128
  }
}
Response · 200
200 OK

{
  "record_id": "rec_8f3ac210",
  "duplicate": false,
  "source": "landing page"
}
Amendment forms

Asking for the one thing that was missing

A phone number came in wrong, a document never arrived. An amendment form changes an existing record instead of creating a second one. The visitor arrives through a link written into an email template, and what that link opens is written into the link. Without it, the form accepts nothing.

  • It shows nothing already stored. The link gives access to add, not a window into the record.
  • An empty field deletes nothing. Leaving a box blank means no answer, not an instruction to clear it.
  • Sending a file afterwards. The usual case, and the reason the purpose exists at all.
  • The purpose is fixed at creation. An intake form cannot quietly become an amendment form later.
Pricing

What the form builder costs

Priced by how many forms you run, not by how many people fill them in. A form that gets a thousand submissions costs the same as one that gets ten, because the submissions become records and those are counted where records are counted.

Form builder, 1 form
$12.42/mo
billed yearly · $15.00/mo billed monthly
Save 17% vs monthly
Create your account
  • 1 form
  • Every builder feature
  • Embedded or as a link
Most popular
Form builder, 3 forms
$20.75/mo
billed yearly · $24.00/mo billed monthly
Save 14% vs monthly
Create your account
  • 3 forms
  • Every builder feature
  • Embedded or as a link
Form builder, unlimited
$33.25/mo
billed yearly · $39.00/mo billed monthly
Save 15% vs monthly
Create your account
  • Unlimited forms
  • Every builder feature
  • Embedded or as a link
Packages, everything else you can buy, and what is in every planPrices in USD, excluding VAT. Reverse charge applies inside the EU.

Questions people ask

If the answer you need is not here, the help center has the long version.

Do I have to rebuild the forms I already run?
No, and we would rather you did not do it on our account. The intake API is the core's way in and is not going away. Move a form when you want what the builder gives you, not because the old one stopped working.
Can I make it look like the rest of my website?
Yes, from your own stylesheet. Colours, corners and fonts come through variables you set on the form's box, and individual parts are addressable by name. The brand stays in one place, which matters at the next redesign rather than today. If you cannot touch the website at all, there is a field for custom CSS inside the form.
Is there a captcha?
No. Three measures run on every form instead: an invisible trap field, a minimum time before a submit is accepted, and a cap per minute. None of them asks a human to identify a traffic light, and none of them is configurable, because a spam setting people tune is a spam setting people get wrong.
Can somebody book an appointment inside the form?
With the scheduling module booked, yes. Pick a time appears in the builder as a block, you place it on a page like a field, and the appointment is booked when the form is submitted. Without that module the block is not offered.
What happens if the confirmation email fails?
The record is already there. Every output carries its own result on the submission, so a failure is visible with its reason, and it stops nothing else. The record is never conditional on an action that runs after it.

Build one form against your own fields

Set up an entity, put a form in front of it, and submit once. That answers more about the fit than any page here.