Forms

A Hyphen form is how a person supplies structured data to a governed process. Two kinds exist and one renderer serves both:

  • A form pause, the PbotForm step. A running case reaches a PbotForm step and waits for named keys. The pause is a task. Submitting resumes the run, once. Rendered with <hyphen-form run-id="…" step-id="…">.
  • An intake form, the external form. A standalone form with a schema and a trigger, created with POST /external-forms. Submitting starts a workflow or a published process with the submission as input. Rendered with <hyphen-form form-id="…">, the launcher, or the hosted page.

The full walkthrough of both is Forms, end to end.

Surfaces at a glance

You want Use Needs
A link anyone can fill https://<gateway>/forms/<formId> a public intake form
A form inside your own page <hyphen-form form-id="…"> the SDK script and your publishable key
A form in your page with no account or key for the visitor <hyphen-form form-id="…" public> the SDK script
A button that opens a form <hyphen-form-button form-id="…"> or data-hyphen-form="…" on any element the SDK script
A form built from a sentence POST /sdk/forms/generate the agent_forms feature on the organization
The forms a case is waiting on <hyphen-task-sidebar>, or GET /sdk/forms/pending an SDK session
Fill a paused step from your own UI <hyphen-form run-id="…" step-id="…"> a signed-in SDK session

<hyphen-form>

Renders an intake form, a paused step, or an inline schema.

html
<!-- An intake form, under your session -->
<hyphen-form form-id="frm-…" submit-text="Send" done-text="Received. We will be in touch."></hyphen-form>

<!-- The same form with no session: uses the public routes -->
<hyphen-form form-id="frm-…" public public-base="https://<gateway>"></hyphen-form>

<!-- A paused step of a running case -->
<hyphen-form run-id="run-…" step-id="2"></hyphen-form>

Attributes

Attribute Type Default Description
form-id string An intake form to render
run-id + step-id string A paused PbotForm step to render instead
schema JSON An inline form_schema_v1 document, for previews. Wins over the form's own schema
public flag off Read and submit through the anonymous public routes; no session
public-base URL the SDK base The gateway origin for public mode
hide-title flag off Hide the form title
submit-text string Submit Label on the submit button
done-text string Message shown after a successful submit

Events

All events bubble and are composed, so they cross the shadow boundary.

Event Data When
hyphen-form:loaded { schema, mode } The schema is resolved and rendered
hyphen-form:page { page, of } The person moves between pages
hyphen-form:submitted { payload, mode, response } The submit succeeded. For an intake form, response carries submission_id, triggered_run_id, and triggered_execution_type
hyphen-form:error { message } Load or submit failed

How It Works

The fields come, in order of precedence, from a schema attribute, the schema authored on the form or the step, a schema generated once for that step when agent_forms is on, or a fallback of one text field per expected key. The submitted payload is always flat: { key: value }.

Submitting a paused step needs a signed-in session. An anonymous publishable-key session can read forms but not settle a pause; the gateway answers 403 with a hint. The engine records who submitted and refuses a second submit with 409.

---

<hyphen-form-button> and data-hyphen-form

A launcher opens a form in an overlay, or navigates to the hosted page.

html
<hyphen-form-button form-id="frm-…" public>Start onboarding</hyphen-form-button>

<!-- Any element becomes a launcher -->
<a href="#" data-hyphen-form="frm-…" data-hyphen-form-public>Dispute a charge</a>

<!-- Navigate to the hosted page instead of an overlay -->
<hyphen-form-button form-id="frm-…" href target="_blank">Open the form</hyphen-form-button>

The launcher emits hyphen-form-button:opened and hyphen-form-button:closed on document.


Pages without a key

A static page that has no publishable key can still render public forms. Call HyphenSDK.defineFormElements() instead of HyphenSDK.init(); it registers only the form elements.


The hosted page

https://<gateway>/forms/<formId> renders a public intake form with no account and no key. The page is noindex, served with no-store, and reads the form through the gateway's anonymous proxy, which never exposes the organization id and rate-limits by IP: 60 reads and 10 submits per form per minute. The page follows the browser's theme; a Theme control in the header switches between auto, light, and dark and remembers the choice, and ?theme=dark or ?theme=light sets it for a link.

A successful submission answers 201 with submission_id, triggered_run_id, and triggered_execution_type (workflow_run or agent_run). The same facts arrive on the organization's webhooks as external_form_submitted.

If Hyphen saves the submitted payload but cannot start the configured run, the endpoint answers 502 form_trigger_failed. The response includes the durable submission_id and a trigger_failed status under error.details, so the accepted payload can be traced without treating the outcome as unknown. The webhook carries the same status.

Who is filling it in. With settings.requireAuth: true, the page asks for an email, sends a one-time code through the organization's existing email delivery, and submits with the resulting session. An unsigned submit on such a form is refused with 401 form_signin_required. The engine records submitted_by on the triggered run and on the webhook.

Branding. settings.branding white-labels the page: name and logoUrl replace the Hyphen wordmark, accent colors the controls, footer replaces the default line, and hidePoweredBy removes it.


Forms a running case is waiting on

When a case pauses on a PbotForm step:

  • the pause is a task: it appears on the SDK event stream as task:created with kind: "form", and GET /sdk/forms/pending lists it;
  • <hyphen-task-sidebar> lists it beside approvals with Fill it in and renders the form inline;
  • Process Studio shows Fill it in on the paused case;
  • <hyphen-form run-id="…" step-id="…"> renders it anywhere.

Webhooks: form_pause_created, form_submitted, form_expired.


Styling

The components render in shadow DOM and read the --hyphen-* tokens from the host element: --hyphen-color-bg, --hyphen-color-text, --hyphen-color-border, --hyphen-color-primary, --hyphen-font-family, --hyphen-radius. Set them on hyphen-form in your stylesheet. See Theming.


Two audiences

A partner embedding Hyphen surfaces forms inside its own product under its publishable key, with <hyphen-form> or the launcher, and reads submissions through its session.

A Hyphen organization shares the hosted link with its clients, brands the page, and turns on sign-in when it needs to know who answered.

→ Next: Forms that start work Ā· Forms, end to end