Help Center
DocsRouting Forms
Qualify before scheduling — route prospects to the right booking page or host based on their answers
A public form that asks qualifying questions, then sends the visitor to the right next step based on their answers.
A routing form lives at /r/[slug]. The visitor answers the questions you configured, and the first matching rule decides what happens next: book a meeting on a specific booking page, route to a specific team member, redirect to an external URL, or display a message. When the rule sends them to a booking page, the answers they just gave are pre-filled on the booking form so they don't have to retype their name, email, or any custom-question responses.
Open Admin → Routing Forms.
Add questions.
Add routing rules.
Set a default action.
Activate and share.
| Field | Description | Type |
|---|---|---|
| text | Single-line input. Up to 500 characters. | string |
| textarea | Multi-line input. Up to 4,000 characters. | string |
| Single-line input validated as a valid email address. | string | |
| phone | Free-form phone number. Up to 50 characters. | string |
| number | Numeric input. Use this when you want to compare ranges (greater than, less than) in routing rules. | number |
| date | Calendar date picker. Stored as YYYY-MM-DD. | date |
| select | Single-choice dropdown. Define 1–50 options as id|Label pairs. | enum |
| multiselect | Multi-choice picker. Same option format as select; the visitor can pick more than one. | enum[] |
| checkbox | Single boolean. Useful for consent or yes/no eligibility flags. | boolean |
| Field | Description | Type |
|---|---|---|
| equals / not_equals | Exact match. Works on text, select, and multiselect (matches when any selected option equals the value). | comparison |
| contains / not_contains | Substring match for text fields, or membership for multiselect. | comparison |
| greater_than / less_than | Numeric comparison. Use on number questions, e.g., "Annual revenue greater than 1000000". | comparison |
| in / not_in | Match against a list of values. Useful when several option ids should route the same way. | comparison |
| is_empty / is_not_empty | No value to type — checks whether the question was answered. The value field is disabled. | comparison |
| Field | Description | Type |
|---|---|---|
| Route to booking page | Send the visitor to /b/[workspace]/[page]. Their name, email, and any custom-question responses are pre-filled via a one-time prefill token (?prefill=...). The token is single-use and expires 30 minutes after the routing decision. | redirect |
| Route to specific host | Same as above, but the booking page must use a team strategy (round_robin, collective, or group). Pass the host's user_id and the booking page locks the booking to that host. | redirect |
| Redirect to URL | Send the visitor to an arbitrary external URL. Useful when an answer disqualifies them — e.g., "Sorry, you're outside our service area — visit our partner page." | external |
| Show message | Display a static message inline on the form page. No redirect. Useful for "Thanks — a sales rep will reach out" responses. | inline |
Rules evaluate in the order they appear in the editor. The first rule whose conditions match wins — its action is what the visitor sees. Subsequent rules are not evaluated. If no rule matches, the default action runs. Drag rules into priority order: put your most specific qualifiers (high-value enterprise, region locks) at the top, broad fallbacks at the bottom.
When a rule routes to a booking page or specific host, the form generates a single-use prefill token. The visitor lands on /b/[workspace]/[page]?prefill=<token> and the booking page looks up the token, fetches the form submission, and pre-fills the booker's name, email, and any answers to questions that match the booking page's custom intake questions. The token is hashed at rest, expires 30 minutes after issue, and can be redeemed only once — so sharing or re-loading the URL after submission silently drops the prefill rather than leaking another visitor's data.
Every submission is stored on the form regardless of which action ran. If the visitor provided an email and the email matches an existing CRM contact, the submission auto-links to that person record. If no match is found and the form was set to capture leads, a new lead is created with the answers attached. The form list view shows the submission count next to each form and the question count.
- Rules and the default action are never returned to the public GET — the visitor only sees questions and labels.
- Submissions are rate-limited per IP (10/hour) and per form (60/hour). Hitting the limit returns a 429 with a
Retry-Afterheader. - Email submissions auto-link to existing CRM contacts only when the email matches exactly (lowercase, parameterized comparison — never
LIKE). - Prefill tokens use 32 cryptographically random bytes, are stored as a SHA-256 hash, are single-use, and expire 30 minutes after the routing decision.
- Inputs are stripped of control characters, capped at sane byte lengths, and validated against the question schema before write — header-injection and XSS-via-prefill are blocked at the system boundary.
- scheduler.view — required to see the routing-forms admin page.
- scheduler.create — required to add a new form.
- scheduler.edit — required to change questions, rules, default action, or activation.
- scheduler.delete — required to remove a form. Submissions persist after deletion for analytics.
- The public
/r/[slug]page is unauthenticated — anyone with the URL can submit if the form is active.