About
Programmatic access to lead-capture (embed) forms: create and update forms, read submissions as they come in, and pull the analytics behind the app’s form dashboards — conversion funnels, traffic sources, engagement time, and lead routing. All operations go through the developer API gateway — one endpoint, called byoperationId. If you haven’t set up a key yet, start with the
Developer API Overview.
Operations
Forms and submissions (READ scope)
Form analytics (READ scope)
Writing forms (WRITE scope)
fieldConfig validationA single-page form uses a flat field array. A multi-step form uses
{ fields, steps, showStepProgress }; each step has a unique id, required
builder-facing name, and optional visitor-facing title, subtitle, and
ctaLabel. Fields point to a page with stepId; an unknown step is rejected.
Two or more steps render the paged experience.Field type is one of text | email | phone | number | dollar | dropdown | multiselect | textarea | checkbox | address | calendar; mapping is
firstName | lastName | fullName | email | phone | address | note | none | customField:<id>; width is full | half | third. Fields may also carry
hideLabel, validation rules, dropdown-to-custom-field option mappings, and
calendarConfig. A calendar field without calendarConfig renders no picker,
so always provide it. At least one field is required and at most one calendar
field is allowed. Malformed entries are rejected with a validation error
naming the field. fieldKey is limited to 200 characters; each
dropdownOptions entry and mapped formOptionLabel is limited to 256.
Longer values reject the whole create or update instead of being truncated.Calendar locations
A calendar field’scalendarConfig.locationType is CUSTOM (the default),
VIDEO_CALL, or PHONE_CALL. CUSTOM uses defaultLocation, such as a
street address or pasted meeting link. VIDEO_CALL uses the join link created
on the host’s calendar: Google Meet, or Microsoft Teams when calendarProvider is
MICROSOFT. PHONE_CALL creates no meeting link: the host calls the number
the booker entered. That mode requires a field with type: "phone",
mapping: "phone", and required: true, or the write is refused.
Always supply the rest of calendarConfig; without it, the calendar field
renders no booking picker.
Routing calendar bookings
SetassignmentConfig to { assignees, teamIds, participantUserIds }.
All three lists are required when supplied and replace the whole pool; omit
the object to preserve it. Read getForm and merge before changing one list.
Each assignee has a same-organization userId; on a calendar form it also
needs calendarConfig: { isFixed, checkExternalCalendars }.
Non-fixed assignees rotate in array order by least recent booking. Fixed
assignees always attend; if all are fixed, the first is the host. Calendar
forms require a non-empty pool and a calendar configuration for every
assignee before activation. Some organizations also require the pinned
Google/Microsoft calendar provider to be connected on first activation;
connect any refused account in the app and retry. A form without a calendar
can activate with an empty pool.
Starting workflows on submission
createForm and updateForm accept input.triggerWorkflowGroupIds, the
complete set of CONTACT workflow group ids to start for each submission’s
contact. Omit the field to leave the wiring untouched; send [] to clear it.
Newly added groups must belong to the organization and be neither archived
nor hidden.
The active version is resolved at submission time, so publishing a new
version does not require rewiring the form. Enrollment follows the workflow’s
enrollment policy; it does not re-evaluate its trigger predicate.
The persisted getForm, createForm, and updateForm responses do not echo
this wiring. Keep the intended full set in your integration when replacing
it. Workflows with no eligible active version are skipped, and an enrollment
failure does not fail the form submission; a successful submission alone
does not confirm a workflow ran.
Standalone marketing consent is for SMSTo enable
showMarketingConsent, also provide non-empty
marketingConsentText that explicitly describes SMS/text messages and a
field with type: "phone" and mapping: "phone". On update, resend the
enabled toggle and the SMS wording together. This records SMS consent;
standalone email consent is not supported by these fields.The full collectSmsConsent block has separate transactional and marketing
wording (smsTransactionalConsentText, smsMarketingConsentText). Enabling
it also displays a marketing checkbox, using default wording when none is
supplied. Configure both deliberately; one consent does not grant the other.
An omitted or null label uses and records the built-in wording; an empty
string renders and records no wording. Supply explicit copy rather than an
empty string. smsDisclaimerText is the paragraph beneath the checkboxes,
not a separate opt-in.Styling is a full replacement
styleConfig controls colors, typography, spacing, borders, inputs, buttons,
form width/padding/shadow, dividers, and sanitized custom CSS on both hosted
and embedded forms. Read the current object with getForm, merge locally,
then send the whole result; {} resets defaults. Unknown keys are ignored at
render time, so use the supported key vocabulary in updateForm’s discovery
detail rather than guessing property names.Organization guardForm operations are org-guarded on the
formId (or id on updateForm): a form
outside your organization returns 403 forbidden. listForms and createForm
take no cross-org id — they list / create under your org. See
Authorization for the model.