BuildBaseBuildBase

Overview

Build a form in the console, submit to it from anywhere without a token, and trigger a workflow.

A form is a schema plus a public endpoint. You define the fields in the console, the submission is stored as a collection record, and form.submitted fires as a workflow trigger.

Forms are the only module besides public plans with unauthenticated endpoints. A submission needs no API token, which is what makes a form embeddable on a marketing site.

curl -X POST \
  https://api.console.buildbase.app/api/forms/public/$ORG_ID/$FORM_ID/submit \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","message":"Interested in the Scale plan"}'
{ "success": true, "message": "Form submitted successfully" }

Before you start

Create the form in the BuildBase console under Forms. It is backed by a collection, so a collection and a published version must exist first. The console creates both when you build a form from scratch.

The three public endpoints

None of these require an Authorization header.

MethodPathReturns
GET/api/forms/public/:orgId/:formIdThe form document — title, settings, collection references
GET/api/forms/public/:orgId/:formId/fieldsThe field schema array from the published collection version
POST/api/forms/public/:orgId/:formId/submit{ success, message }

:orgId must be a valid ObjectId or the request is rejected before lookup. An unknown formId returns 404 with {"error": true, "message": "Form with id ... not found"}.

Submitting

The request body is the data object. Keys are field slugs — there is no wrapper:

{ "email": "[email protected]", "plan": "scale", "seats": 12 }

Each submission creates a collection record carrying collectionId, versionId, formId, and your data, then emits form.submitted with the form ID, the new record ID, and the submitted data.

Validation

The server validates the payload against the published field schema before writing anything.

A collection field is one of eight types. Only four are validated on submit:

Field typeRule
any, required: trueRejected when undefined, null, or ''
numberMust be a number or a numeric string
emailMust match a basic [email protected] pattern
linkMust start with http:// or https://
dateMust parse with Date.parse()
text, rich-text, colorStored as sent, no format check
boolNot validated — see below

Empty optional values skip every check, so a rule only applies to a field the submitter actually filled in.

Warning

Boolean fields are not validated. The validator branches on the string boolean, but the type's stored value is bool, so the branch never runs. Any value at all — "yes", 42, an object — is accepted into a bool field and stored verbatim.

Coerce booleans client-side, and treat the stored value as untrusted when you read records back.

Note that email and link only validate when the submitted value is a string. A number or object sent for those fields skips the format check the same way.

A failure returns 400 with every error at once, not just the first:

{
  "success": false,
  "message": "Validation failed",
  "errors": ["Email must be a valid email", "Seats is required"]
}

Note this uses success: false, unlike most API errors which use error: true. Branch on the HTTP status rather than the body shape.

Warning

The public submit endpoint has no CAPTCHA and no spam filtering. The only limit in front of it is the global API rate limiter — 500 requests per 3 seconds per IP — which is a flood guard, not bot protection. A single client can submit far faster than any human and stay well under it.

Put your own bot protection in front of a publicly embedded form, or proxy submissions through your backend.

Triggering a workflow

form.submitted is a workflow trigger under the Forms category, and one of 86+ events in the system event catalog. A common shape:

  1. Visitor submits the form.
  2. Record is written to the collection.
  3. form.submitted fires.
  4. A workflow sends a confirmation email and posts to Slack.

The event payload carries formId, recordId, and the full data object, so merge tags in the workflow can address submitted fields directly.

Next Steps

  • Custom forms — render your own UI against the field schema.
  • Workflows — act on form.submitted.
  • Admin API — read submissions back through the collections API.