Resources
Define forms, webhooks, and schedules as workflow entry points.
What it is. The ways the outside world hands input to your system: forms collect it from people, webhooks accept it from programs, and schedules generate it on a clock.
Use it when you have forms today (Google Forms, Typeform, your website), apps that can call a webhook, or a procedure you run on a schedule.
Works with triggers (the binding that starts the workflow) and auth blocks (basic-auth gating for public forms).
Resources are the entry points for your workflows. Each resource type generates a trigger that starts a workflow run. Connect resources to workflows using triggers.
Forms
A form defines an input interface with a JSON Schema for its payload. Swirls renders the form as HTML and hosts it at a public endpoint. You can inline the schema with @json { … } or define a reusable top-level schema block and set schema: my_schema_name on the form (and on workflow nodes) so one definition is shared across triggers and steps.
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Display name |
description | string | No | Description shown in the Portal |
visibility | string | No | public or internal. Defaults to internal. |
enabled | boolean | No | Whether the form is active |
auth | identifier | No | Name of a top-level auth block with type: basic for HTTP Basic auth gating |
schema | json block or name | No | JSON Schema for the form payload, or a reference to a schema resource |
Visibility. public forms are served at /triggers/forms/:projectId/:formName. internal forms return 404 from the Triggers service. The default is internal.
HTTP Basic auth. Set auth: <block_name> where the referenced auth block has type: basic. The Triggers service requires a valid Authorization: Basic header before rendering or accepting the form.
schema contact_payload {
label: "Contact payload"
schema: @json {
{
"type": "object",
"required": ["name", "email", "message"],
"properties": {
"name": { "type": "string", "title": "Name" },
"email": { "type": "string", "title": "Email" },
"message": { "type": "string", "title": "Message" }
},
"additionalProperties": false
}
}
}
form contact_form {
label: "Contact Form"
description: "Collect contact information"
visibility: public
enabled: true
schema: contact_payload
}A password-protected internal form:
secret portal_auth {
vars: [PORTAL_USER, PORTAL_PASS]
}
auth portal_basic {
type: basic
secrets: portal_auth
username: PORTAL_USER
password: PORTAL_PASS
}
form internal_intake {
label: "Internal Intake"
visibility: internal
auth: portal_basic
enabled: true
schema: contact_payload
}Webhooks
A webhook defines an HTTP POST endpoint. The Triggers service accepts payloads at /triggers/webhooks/….
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Display name |
description | string | No | Description |
enabled | boolean | No | Whether the webhook is active |
schema | json block or name | No | JSON Schema for the expected payload |
secret | <block>.<var> | No | Reference to a secret var for shared-secret verification |
header | string | No | Header name that carries the shared secret (e.g. "X-Hub-Signature-256") |
Without secret and header, the webhook is anonymous. The Portal warns when a webhook has no shared-secret verification.
secret stripe_creds {
vars: [STRIPE_WEBHOOK_SECRET]
}
webhook stripe_events {
label: "Stripe Events"
enabled: true
secret: stripe_creds.STRIPE_WEBHOOK_SECRET
header: "Stripe-Signature"
schema: @json {
{
"type": "object",
"required": ["type", "data"],
"properties": {
"type": { "type": "string" },
"data": { "type": "object" }
},
"additionalProperties": false
}
}
}Schedules
A schedule triggers a workflow on a cron expression.
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Display name |
cron | string | Yes | Cron expression |
timezone | string | No | IANA timezone (e.g. "America/New_York") |
enabled | boolean | No | Whether the schedule is active |
schedule daily_report {
label: "Daily Report"
cron: "0 9 * * *"
timezone: "America/New_York"
enabled: true
}Connecting resources to workflows
Resources do not run workflows on their own. You connect a resource to a workflow using a trigger. See Triggers for details.