Skip to main content
When volunteers fill out a Form in VOMO — a waiver, a signup question, a post-event survey — the result is a Form Completion record. Form Completions are read-only via the API (volunteers submit them through VOMO; partner integrations consume them), but they’re often the richest source of structured data about volunteers’ preferences, eligibility, and feedback. This workflow page walks through reading Form Completions: how to find them, how to display them with their field context, how to filter by user or time range, and how to sync them to external systems for reporting or follow-up. If you haven’t yet, skim the Forms and Form Completions concept page for the five-resource family structure and field shapes.

When to use this workflow


The three endpoints involved

⚠️ Spec gap (audit #19, #20): The path parameter for the single-completion endpoint is {completion} (not the more conventional {completionId}), and the parameter descriptions in the spec contain typos (“VOMO From ID” instead of “VOMO Form ID”). The endpoints work as documented; the naming will be cleaned up in a future spec revision.

Step 1: Find the Form

If you have the Form ID already, skip to Step 2. Otherwise, find it from the Forms list:
JavaScript
For partner integrations, the typical pattern is to configure the Form ID once during onboarding rather than looking it up by name every time:
JavaScript
The configured ID is more robust than name-based lookup (Form renames don’t break the integration) and avoids the per-call lookup cost.

Step 2: List completions

GET /forms/{id}/completions returns the Completions for that Form, paginated with the standard data/links/meta envelope:
cURL

Available filters

A reference paginate function:
JavaScript

Common list patterns

All completions of a Form (e.g., everyone who’s signed the waiver):
JavaScript
One user’s completions of a Form:
JavaScript
Completions since the last sync:
JavaScript
The created_after filter is the primary incremental sync mechanism — feed it the timestamp of the last completion you processed.

Step 3: Read responses with context

The Form Completion’s field_responses array contains the volunteer’s answers, but each response is just { field_id, value } — without the Form’s field definitions, you don’t know what question was asked or what type of input the value represents. The pattern: fetch the Form once, then join responses with field definitions when displaying:
JavaScript
The output is a displayable Completion — question text, field type, and parsed value per response — suitable for showing in a UI: “Bruce Wayne’s General Volunteer Waiver submitted 2025-04-19.”

Parsing values by field type

Different field types need different parsing:
JavaScript
The exact storage format for MULTIPLESELECT (comma-separated vs. JSON array) isn’t documented in the spec — the pattern above handles the most likely format defensively.

Caching the Form definitions

For workflows that process many completions of the same Form, cache the Form (the field definitions) so you don’t re-fetch on every completion:
JavaScript
Forms change infrequently — caching for the duration of a sync run (or longer) is safe.

Scenario 1: Display a user’s form history

For a partner UI showing “all forms this volunteer has submitted”:
JavaScript
This is N+1 (one Forms list + one Completion list per Form). For accounts with many Forms but where most users have few completions, this is acceptable. For high-volume accounts, consider:
  • Limit to specific forms the user is likely to have completed (waivers, role-specific forms)
  • Cache the result per user (Form history changes only when new completions arrive)
  • Run nightly and cache for the next day’s display

Scenario 2: Detect waiver expiration

For organizations requiring annual waiver renewal:
JavaScript
Feed the result into the customer’s renewal outreach pipeline. Run on a schedule (weekly or monthly) and email/notify users approaching their renewal deadline.

Comparing against active volunteers

A more nuanced version: only consider users who are currently active (have recent participations):
JavaScript
This narrows the renewal list to volunteers who are actually engaged — avoiding outreach to dormant users.

Scenario 3: Sync completions to an external system

For partner integrations mirroring Form data into an external CRM or analytics platform:
JavaScript
Run on a schedule per Form the customer wants synced. The high-water-mark pattern (advancing to the latest created_at actually seen) ensures interrupted syncs resume correctly.

Triggering follow-up workflows

For workflows that need to react to new completions (e.g., send a welcome email when a new waiver is signed):
JavaScript
Run on a polling interval (every 15 minutes for “near-real-time,” hourly for less urgent workflows). See Polling and Sync for the broader pattern.

Scenario 4: Aggregate responses for reporting

For survey or feedback forms where you want aggregate statistics:
JavaScript
The output is a per-field distribution suitable for charts, reports, or BI exports.

Performance considerations

A few practical considerations for production-scale workloads: See API Performance Tips for the broader patterns.

What can’t be done via the API

If a partner integration needs to push externally-collected Form data into VOMO (e.g., waivers signed through a third-party legal service), the typical path is:
  1. Capture the completion data externally
  2. Store a reference linking the external completion to the VOMO User
  3. Coordinate with the customer’s admin team for periodic CSV import into VOMO — or skip the VOMO sync entirely if the external system is authoritative
See Understand Write Limitations.

Where to go next

Understand Write Limitations

The reference for what can and can’t be done through the API.

Forms and Form Completions

The reference page for Form resource fields and the field-type values.

Polling and Sync

The broader change-detection pattern for incremental sync workflows.

Users

Form Completions link back to Users via user_id.
Last modified on May 22, 2026