Internal documentation for developers. This page covers the Forms API: form creation, chat widget embedding, submission processing, and the form builder schema. Not intended for end users.
Route Map
Auth Pattern
Forms have dual access patterns: Authenticated (dashboard):POST /api/forms/[formId]/chatcan be called without authentication- Protected by
formIdsecrecy (HMAC-signed if needed)
Form Schema
Forms are defined as a JSON schema stored in theconfig field:
Chat Submission Endpoint
ThePOST /api/forms/[formId]/chat endpoint processes a form submission through the AI:
Streaming Contract
forms/[formId]/chat/route.ts returns a text/event-stream response immediately, then delegates execution to the assigned agent through /api/agents/[id]/query. The route buffers endpoint_response chunks and validates the final payload with ChatResponse.safeParse before reading answer, messageId, or metadata.
The route emits metadata SSE events only for typed form-state updates:
messageId is present, the persisted message is updated with the marker-stripped answer and the typed form metadata. Parsing failures in tool or endpoint buffers are ignored deliberately; malformed buffers do not create partial database writes.
Submissions
Prisma Indexes Used
Known Issues / Gotchas
- Public chat endpoint: The
formIdis the only secret protecting public form submissions. For sensitive forms, consider adding HMAC signing or reCAPTCHA. - Submission JSON schema evolution: If form fields change after submissions exist, old submissions may have fields that no longer match the current schema. UI must handle missing fields gracefully.
- AI processing timeout: The chat submission endpoint calls the AI, which can take up to 30 seconds for complex forms. Configure appropriate Next.js function timeout.
- Webhook delivery: External webhook on submit is fire-and-forget. Implement retry logic in
@zappway/lib/webhooksif reliability is required.

