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
| Scenario | This workflow fits |
|---|---|
| Mirror Project metadata to an external system | ✓ Primary use case |
| Generate iCal feeds that stay current | ✓ Detect schedule changes |
| Detect new Project Dates added to a Project | ✓ With the schedule-change pattern |
| Notify volunteers when a Project’s policy changes | ✓ |
| Sync the org’s full Project catalog to a data warehouse | ✓ |
| Detect new participants for a specific Project Date | ✗ Use Project Date polling instead |
| Detect when a Project Date’s participants change | ✗ Same |
| Find Projects with available capacity | ✗ This is a query, not change detection |
The baseline pattern
JavaScript
Useful filters for Project polling
Projects support more filter parameters than Users — useful for narrowing the polling scope:| Parameter | What it filters by |
|---|---|
updated_after | Projects modified since X |
active | true/false — only active Projects |
published | true/false — only published Projects |
anytime | Include “anytime” Projects (no specific dates) |
org_slug | Filter to one or more organizations (comma-separated) |
name_like | Substring match on name |
dates_before | Projects with dates before X |
dates_after | Projects with dates after X |
JavaScript
Per-organization polling
For multi-org customers, polling can be split by child organization:JavaScript
What updated_at captures for Projects
The Project’s updated_at advances when:
| Change | Advances updated_at? |
|---|---|
| Project’s name or description changes | ✓ Yes |
age_limit, allow_guests, or policy changes | ✓ Yes |
draft status flips (publish or unpublish) | ✓ Yes |
privacy setting changes | ✓ Yes |
| Address change | ✓ Yes |
| Schedule modification (Project Dates added, removed, or modified) | ✓ Likely (confirm with live behavior) |
Project’s campaigns attachment changes | ✓ Likely |
| A new participant signs up for a Project Date | ✗ No — see Detecting participant changes |
| A participant checks in/out | ✗ No |
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’supdated_at advances, the change might be:
- Metadata (name, description, policy)
- Schedule (Project Dates added, removed, or modified)
- Both
all_dates to a previous snapshot:
JavaScript
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
Detecting participant changes
Participants on a Project Date are not detected by polling Projects. The Project’supdated_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
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
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:| Workload | Suggested cadence |
|---|---|
| Project metadata sync | Hourly |
| Schedule mirroring (iCal, calendar feeds) | Every 1-2 hours |
| Per-org Project catalogue refresh | Every 4-6 hours |
| Participant detection (Option A — per Date) | Every 15-30 minutes for active dates |
| Full participant scan (Option C) | Daily |
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 sameupdated_at:
JavaScript
Handling deletions
Like Users, Project deletions aren’t detected throughupdated_after polling. The same reconciliation pattern applies:
JavaScript
Why the per-ID detail fetch
A Project missing from the filtered list could be:- Genuinely deleted (returns
404on detail fetch) - Set to
draft: true(no longer inpublished: truelist) - Set to
active: false(no longer inactive: truelist) - Outside the date filter window (if you used one)
A reference project-change poller
JavaScript
Monitoring
Per-customer metrics worth tracking:| Metric | What it tells you |
|---|---|
| Projects changed per poll cycle | Activity level; spike may indicate bulk admin changes |
| Schedule diffs per cycle (added/removed/modified) | What kind of changes are happening |
| Time since last checkpoint advance | Polling worker health |
| Failed Project processing rate | Per-Project errors needing investigation |
| Detail-fetch latency | API health proxy |
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_atactually 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.