Lead capture and the interest list
Open in
Each form on the landing site, and the same form as an agent's tool, turns a visitor into a contact kept with its consent.
Each step is a state of the contact, written as an Event. Filled: what the visitor sees.
A demo form
The sales tracker's demo form asks for three fields. Each confirmed contact is enriched, then written to the team's CRM.
import { define } from 'apis.dev'
/** Deals for each Customer, with a demo form that writes each confirmed visitor to the team's CRM. */
export default define({
name: 'pipeline', domain: 'pipeline.apis.dev',
sources: {
firms: { api: 'companyfacts.apis.dev', cost: { 'Company.get': 0.002 } },
crm: { system: 'crm', scope: 'you', sync: 'write' },
},
Company: { name: 'string', domain: 'url!#', deals: '<-Deal.company' },
Deal: {
title: 'string', amount: 'decimal(12, 2)', company: '->Company.deals',
stage: { open: [], qualify: 'opened', win: 'qualified', lose: ['opened', 'qualified'] },
},
offer: {
Free: { month: 0, seats: 1, includes: { 'Deal.open': 25 } },
Team: { month: 49, seats: 5, includes: { 'Deal.open': 1000 } },
'Deal.open': 0.001,
},
leads: {
forms: { demo: ['email', 'company', 'useCase'] },
confirm: true, // one link before anything else
enrich: { api: 'companyfacts.apis.dev', cost: 0.002 }, // a lookup per contact
to: 'crm',
},
})Your team reads a contact with Contact.list on the Operator plane; the CRM receives the same record.
HTTP/1.1 200 OK
Content-Type: application/ json
X-Cost: price= 0, currency= "USD"
X-Request-Id: req_8e2b47d0c3f91a65b7e4
{
"id": "con_12",
"email": "dana@acme.com",
"form": "demo",
"source": "forms",
"state": "synced",
"consent": { "broadcasts": true, "at": "2026-10-28T10: 02: 11Z",
"notice": "sha256: 6a1f0c33" },
"answers": { "company": "Acme", "useCase": "Track enterprise deals" },
"enriched": { "employees": 240, "sector": "Software", "cost": 0.002 },
"customer": null
}Where a visitor leaves an address
A contact joins the interest list, beside every unmet call, pre-order and sign-up, in the order each arrived.
| A visitor | Meets | The contact's source |
|---|---|---|
| On the landing site | Each form in leads.forms, at its own path, with the fields it names | forms |
| An agent for a person | The joinInterestList tool over MCP, with the same fields as input | forms |
| A caller whose call missed | The 402's or 404's offer to hear when it serves | interest |
| A buyer of a pre-order | Its Checkout | preorders |
Each form meets the bar for generated pages, and the edge challenges bots before it accepts one. A refused submission costs nothing and writes no contact.
Enrichment, at its posted price
Enrichment reads another API product as a Source: one lookup, at its posted price, per contact.
That price is the whole cost, with no fee on top. A lookup that misses costs what the enriching product charges for a miss.
With confirm on, enrichment waits for the confirmed address. It never runs on a personal address, such as one at a webmail domain.
Consent, and an erase that reaches the CRM
The form asks for consent to broadcasts in its own unticked box, and keeps the notice version beside the answer.
A contact who never ticked it still gets the confirmation and the reply it asked for, and nothing else. An unsubscribe joins the suppression list at once.
Contact.erase removes the contact from the product, the interest list and the CRM it synced to, and keeps only its suppression. Lead capture into a CRM, with enrichment, is a Team feature.
Ask, answers from your docs
Cited answers over your product's docs for your Customers and their agents, on the docs, in the portal and over MCP, with a person one step away.
Broadcasts
One message to contacts and Customers who consented: approved, sent in each reader's timezone, unsubscribed in one click, and posted to a feed agents read.