Skip to main content
Projects change less frequently than Users but matter more per-change. A renamed Project, a modified schedule, an added Project Date — these often have downstream implications for partner integrations: updated external calendar feeds, refreshed reporting dashboards, notifications to interested volunteers. This page covers Project-specific polling: how updated_after works for Projects, what changes are (and aren’t) captured, how to detect schedule changes, and how participant detection sits adjacent to (but distinct from) Project polling. If you haven’t yet, skim the Polling Overview for the foundational pattern.

When to use this workflow


The baseline pattern

JavaScript
Hourly is a reasonable starting cadence for Projects. Most Projects change a few times during their setup phase and then stay stable; constant polling produces minimal change but consumes rate budget.

Useful filters for Project polling

Projects support more filter parameters than Users — useful for narrowing the polling scope: A common production pattern: poll only active, published, recent Projects:
JavaScript
This narrows polling to Projects that actually matter for downstream workflows. Drafts and archived Projects are skipped, reducing both API request volume and downstream noise.

Per-organization polling

For multi-org customers, polling can be split by child organization:
JavaScript
This allows different child orgs to have independent polling cadences, checkpoints, and processing logic — useful when partner integrations route data to per-org destinations.

What updated_at captures for Projects

The Project’s updated_at advances when: The schedule-change behavior is the most important one to verify in your environment. Most integrations treat “Project’s updated_at advanced” as a signal to re-read the full Project (including all_dates) to detect what changed.

Detecting schedule changes

When a Project’s updated_at advances, the change might be:
  • Metadata (name, description, policy)
  • Schedule (Project Dates added, removed, or modified)
  • Both
To detect schedule changes specifically, compare the current all_dates to a previous snapshot:
JavaScript
The pattern: detect that the Project changed (via polling), fetch the full detail (with embedded all_dates), diff against the last-known snapshot, and emit per-change events. This adds cost (one detail fetch per changed Project), but it’s how you turn a “Project changed somehow” signal into “this specific Project Date was added at this time.”

Storing the schedule snapshot

The snapshot is per-Project, per-customer. A simple structure:
JavaScript
Update the snapshot after each successful processing. The next polling cycle uses it as the comparison base.

Detecting participant changes

Participants on a Project Date are not detected by polling Projects. The Project’s updated_at doesn’t advance when a participant signs up or checks in. For partner integrations that need participant-change detection:

Option A: Poll Project Dates separately

For each active Project, poll its Project Dates’ participants on a schedule:
JavaScript
Cost: One detail fetch per Project Date per poll cycle. For a customer with 10 active Projects, each with 3 upcoming Dates, that’s 30 requests per cycle. Throttle accordingly.

Option B: Bound the polling scope

Don’t poll all participants for all Project Dates — limit to:
  • Projects you specifically care about (configured by customer)
  • Project Dates in a recent time window (past week + next week)
  • Project Dates that have changed participant_count (compare against snapshot)
JavaScript
The participant_count field on all_dates is updated by VOMO when participants are added or removed. Using it as a tripwire avoids fetching detail for Project Dates that haven’t changed.

Option C: Periodic full participant scan

For integrations where participant detection isn’t real-time, scan periodically (daily or weekly) and reconcile against the last snapshot. See Reconciliation Patterns.

Cadence considerations

Projects change less frequently than Users, so polling can be less aggressive: A common pattern: Projects polled hourly; participants polled more frequently but only for “active” Project Dates (those within a recent or upcoming window).

Combining metadata and schedule polling

For most integrations, one polling worker handles both metadata changes and schedule changes — they happen at the same cadence because they share the same updated_at:
JavaScript
The cost: list query + one detail fetch per changed Project. For an account with stable Projects (most days no changes), this is cheap. For periods of active scheduling changes, it scales linearly.

Handling deletions

Like Users, Project deletions aren’t detected through updated_after polling. The same reconciliation pattern applies:
JavaScript
Run daily or weekly. See Reconciliation Patterns.

Why the per-ID detail fetch

A Project missing from the filtered list could be:
  • Genuinely deleted (returns 404 on detail fetch)
  • Set to draft: true (no longer in published: true list)
  • Set to active: false (no longer in active: true list)
  • Outside the date filter window (if you used one)
The detail fetch distinguishes these cases. Without it, you might propagate “deleted” to external systems for Projects that were merely unpublished.

A reference project-change poller

JavaScript

Monitoring

Per-customer metrics worth tracking: A polled-Project-without-schedule-diff is mostly a metadata change. A polled-Project-with-many-schedule-diffs may indicate a customer doing bulk scheduling — interesting for capacity planning.

Production checklist

For a Project-change polling worker:
  • Polling filters to active: true, published: true (or whatever scope the integration cares about)
  • Checkpoint persisted per-customer
  • Checkpoint advanced to latest updated_at actually seen
  • Detail fetch per changed Project for schedule diff
  • Schedule snapshot stored externally per-Project
  • Per-Project processing failures isolated; logged and queued
  • Schedule diff computes added/removed/modified per Date
  • Rate-limit-aware throttling
  • Deletion detection runs as a separate reconciliation
  • Participant detection (if needed) runs as a separate poller
  • Per-customer monitoring dashboards

Where to go next

Reconciliation Patterns

The slow-scan patterns for deletion detection and gap recovery.

Change Detection Best Practices

The cross-cutting patterns — checkpointing, idempotency, drift.

Detecting User Changes

The User-specific polling pattern.

Projects and Project Dates

The reference for Project resource fields and the all_dates / next_date pattern.
Last modified on May 22, 2026