Nextcloud Forms as a synchronization source, and outbound answer mapping
Integriq can read a Nextcloud Forms form's submissions into a
synchronization, and map a Forms submission's answers — resolved by
question, not raw numeric position — into an outbound call to an external
system on the Forms submission trigger, using the same Source →
Synchronization → SynchronizationContract machinery, CallService
transport, MappingService transformation, and EventService
subscription-dispatch pipeline as every other source/target kind.
Forms is a soft (feature-detected) runtime dependency: when the Forms
app is absent or disabled, the nextcloud-form kind simply does not appear
in the synchronization editor, and any synchronization or outbound mapping
subscription already configured with it fails cleanly with a "Forms app is
not enabled" config error before any HTTP call is attempted.
Note: the exact Forms OCS route base path (
index.php/apps/forms/api/v3/...) is TENTATIVE — verified against the publicnextcloud/formsupstream source, not a live instance with theformsapp installed. If a live instance shows the OCS-envelopedocs/v2.php/...form is required instead, only the internal REST client's base path needs to change — nothing else in this document.
Two directions, one client
- Inbound (
nextcloud-formsync source): reads a form's submissions page-by-page into the existing mapping/transformation pipeline — read only, there is nonextcloud-formtarget. - Outbound (submission → external call): on a Forms submission event, a
new
event_subscription.action.kind: 'mapping'fetches the full submission's answers, resolves them by question, runs them through aMapping, and calls an external system viaCallService.
Both directions go through the same Forms API client, so the Source (and its credential) configured for one direction works for the other.
How the source is modelled
A nextcloud-form synchronization's sourceId points at an ordinary
Source object (register openconnector, schema source) — no new
entity type. The Source's location is the base URL of the Nextcloud
instance hosting the form, and its authentication is a normal Basic Auth
credential (or a brokered credentialRef), exactly like any other HTTP
source. Form-specific settings live in the free-form config blob:
| Config key | Side | Meaning |
|---|---|---|
formId | source | The Forms form id (required, integer). |
Forms as a source
Integriq reads submissions page-by-page
(GET .../forms/{formId}/submissions) and feeds each submission (including
its answers) into the mapping pipeline exactly as any other source's
fetched objects. The Forms submission id is used as the origin id, and
change detection uses the same order-independent hash as every other
source. nextcloud-form is source-only — writing submissions into
Forms is out of scope.
Answer-by-question resolution
A Mapping (or an outbound action.kind: 'mapping' configuration)
references a question either by its numeric id (always unambiguous) or
by its exact text:
- A text reference matching exactly one question resolves via that question's id.
- A text reference matching two or more questions is a hard config error naming the ambiguous text and every matching question id — never a first-match guess.
- A
multiple/multiple_unique-type question (checkbox/multi-select) resolves to an array of every selected option's text; every other question type resolves to a single scalar, ornullwhen unanswered.
Outbound: submission → external call
An event_subscription matching a Forms submission event can declare:
{
"action": {
"kind": "mapping",
"mappingId": "<mapping uuid>",
"sourceId": "<source uuid>",
"endpoint": "/leads",
"method": "POST"
}
}
The Forms submission trigger's own event payload does not carry the
submission's answers, so the dispatch independently fetches the full
submission (and the form's questions) via the Forms API before resolving
answers, running the Mapping, and calling CallService::call() against
the resolved Source/endpoint. Success and failure follow the same
retry/backoff/dead-letter machinery as a webhook/synchronization/job
action — a resolution or mapping failure for one submission does not
permanently misconfigure the subscription.
Editor UI
In the synchronization editor, selecting the Nextcloud Form source kind lets you:
- Pick the Source whose credential reaches the Forms API.
- Pick a form the source can access (fetched live).
- See a read-only field reference list of the form's questions (id,
text, type), which visually flags array-valued (
multiple/multiple_unique) questions and any question text that is ambiguous within the form — so you know exactly which id/text references are safe to use before writing aMappingor outbound action configuration.
The kind is only offered as a source; it is never offered as a target kind, regardless of whether Forms is enabled. It is only offered at all when the backend reports the Forms app is enabled.
Out of scope
- Writing submissions into Forms from external data.
- Building/editing forms in Integriq.
- Forms submission-created events as a synchronization trigger — that is
covered by the
nextcloud-event-hub/nextcloud-event-triggerschange; this document only covers thenextcloud-formsource and theaction.kind: 'mapping'outbound dispatch it feeds.