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
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.
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 roof
Four questions, then we know whether it is worth a call.
It travels as a header: Authorization: Bearer key_…
It sits in the address rather than in a header: /api/v1/in/{token}
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.
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.
- 09:41:12200landing pagerecord created
- 09:38:04200Google Adsduplicate, existing record updated
- 09:31:55422partner formpostcode is not a number
- 09:30:02200landing pagerecord created
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 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.
POST /api/v1/records
Authorization: Bearer key_…
{
"entity": "rooftop_de",
"data": {
"first_name": "Marie",
"email": "m.kerner@example.de",
"postcode": "53111",
"roof_area": 128
}
}200 OK
{
"record_id": "rec_8f3ac210",
"duplicate": false,
"source": "landing page"
}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.
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.
- 1 form
- Every builder feature
- Embedded or as a link
- 3 forms
- Every builder feature
- Embedded or as a link
- Unlimited forms
- Every builder feature
- Embedded or as a link
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.