Skip to main content
The Volunteer API exposes Project scheduling data through three different endpoints, each suited to a different purpose. Choosing the right one for a workflow can be the difference between an integration that scales gracefully and one that drowns in unnecessary requests. This workflow page walks through the three endpoints, when to use each, how to combine them, and the practical patterns for common scheduling integrations — calendar views, daily dashboards, participant rosters, and external-calendar sync. If you haven’t yet, skim the Projects and Project Dates concept page for the Project vs. Project Date distinction and the field shapes.

When to use this workflow


The three endpoints

The right choice depends on what you have and what you want. The decision tree:

Scenario 1: Get a Project’s full schedule

For a known Project, the most efficient way to get its full schedule is GET /projects/{id} — the response includes all_dates and next_date embedded, so you don’t need separate Project Date fetches.
cURL
A successful response (relevant fields):

What you get without extra calls

all_dates[] includes for each Project Date: This is enough for calendar views, scheduling displays, and most “show the schedule” workflows. You don’t need to call GET /projects/date/{id} unless you also need the per-Date participants.

When you need more than all_dates provides

all_dates doesn’t include:
  • Per-Date participants (which volunteers signed up for which shift) — requires GET /projects/date/{id}
  • Per-Date custom data (if the customer added Project-Date-specific fields)
For workflows that need participants per Date, see Scenario 4: Get participants for a specific shift.

next_date for “next upcoming shift” displays

The next_date field is convenient for UIs showing “your next opportunity” — it’s the chronologically-nearest future Project Date, pre-computed:
JavaScript
For a “what’s coming up?” homepage card, this is the single right field.

Scenario 2: Daily operational dashboard

For check-in staff or operations dashboards showing “what’s happening today”:
cURL
Returns a list of HappeningResource objects — all Project Dates scheduled for today, across all of the organization’s Projects:

What this is good for

Note: today’s Project Dates, not Projects

The response is Project Dates (Happenings), not Projects. A single Project running a morning and afternoon shift today appears as two entries. To roll up to Projects:
JavaScript
This produces a Project-keyed view: “Saturday Food Bank Shift has two shifts today (9-12 and 2-6).”

The cost of “today” + drill-down

The pattern above is N+1 — one /projects/today call plus one /projects/date/{id} per Happening. For organizations with many simultaneous shifts (10-20+ on a given day), this can be expensive. Caching the per-Date detail helps:
JavaScript
5-minute cache TTL is reasonable for “today” workflows — participants change but not so fast that 5-minute lag matters for most dashboard use cases.

Scenario 3: Find Projects with available slots

For partner-built signup interfaces, find Projects with upcoming Dates that have capacity:
JavaScript
The pattern uses next_date to avoid fetching all dates for each Project — efficient for the common “find a shift to volunteer for” use case. For more sophisticated filtering (e.g., “find shifts with at least 5 open spots”), iterate all_dates:
JavaScript

Scenario 4: Get participants for a specific shift

When you need to know who’s signed up for a specific Project Date:
cURL
Returns the Project Date with its participants embedded:
⚠️ Spec gap (audit #4): This endpoint uses empty schema: {} in the spec — the response shape is documented only through the inline example. Build parsers from observed live responses.
⚠️ Spec gap (audit #34): The endpoint’s path /projects/date/{id} is unconventional (verb-like singular noun). A future revision may rename it to /projects/{projectId}/dates/{dateId}. Until then, the current path is what works.

The participants embedded here

Each participant entry has: This shape includes the Participation data inline (rather than requiring a separate fetch through the User detail). It’s the cleanest path to “who’s signed up for this shift?”

Parsing the participants defensively

JavaScript
The defensive parsing handles:
  • hours returning as a string ("4.00") instead of integer per audit #40
  • verified returning as 0 or 1 integer (treat as boolean)
  • Missing optional fields

Scenario 5: Build an iCal feed for a Project

A common partner workflow: generate an iCalendar (.ics) feed of a Project’s schedule for the customer’s external calendar systems:
JavaScript
The one GET /projects/{id} call gives you the full schedule needed for the feed — no per-Date fetches required. For workflows generating iCal feeds for many Projects simultaneously, cache aggressively — Project schedules change infrequently.

Scenario 6: Multi-Project schedule view

For “all upcoming shifts” displays spanning multiple Projects:
JavaScript
This is N+1 (one Project list + one detail per Project). For accounts with many Projects, throttle and cache:
JavaScript
A 5-minute cache balances freshness with API cost — schedules don’t change so quickly that 5-minute lag matters for most “what’s coming up?” displays.

Choosing the right endpoint

A summary table for quick decisions: The pattern is roughly: use the most-embedded endpoint that has what you need, then drill down only when necessary. The Project detail endpoint is the workhorse for most workflows.

What can’t be done via the API

See Understand Write Limitations.

Where to go next

Create or Update a Project

The companion write workflow — modifying the schedule is done by updating the Project.

Inspect Form Completions

The next supplementary workflow.

Projects and Project Dates

The reference page for the field shapes used here.

API Performance Tips

The caching patterns that make multi-Project schedule reads scale.
Last modified on May 22, 2026