How to Consume Our Data
The published public/data/ contract behind this site — everything a script, agent, or integration needs to reconstruct our opportunity data.
The reconstruction contract
Given partners.json plus each partner's referenced events.json
and past-events.json files, no other data source — no API key, no database,
no source code — is needed to fully reproduce this site's opportunity data. Every file
below is a plain, publicly-served JSON file with no authentication.
These files are generated at build/publish time by the scraper pipeline
(export/publish.py::project()) and served as static assets. This page
never fetches them live — everything shown below is a hand-authored, static example
of the real shape, kept accurate by an automated field-name check.
A note on naming
The pipeline's own curated partner roster (the input it reads) also happens to be named
partners.json, but lives at a different path and has a different shape. This
page documents only the published output,
public/data/partners.json — not the curated input file. Don't confuse the two.
File 1: the partner roster — partners.json
Served at /data/partners.json. A single JSON object: an envelope of
generated_at (an ISO 8601 UTC timestamp) and partner_count,
wrapping a partners array. Every element is a partner organization record —
its directory fields (name, description, location, website, contact info, logo, etc.)
plus three fields added specifically for this contract:
| Field | Description |
|---|---|
slug | Stable, URL-safe identifier for this partner. Used as the directory name in File 2's path. |
events_url | Path to this partner's current/upcoming events file, resolved relative to public/data/ (e.g. partners/example-stem-center/events.json). |
past_events_url | Path to this partner's past-events file, resolved the same way as events_url. |
File 2: per-partner events — events.json / past-events.json
Served at /data/partners/<slug>/events.json and
/data/partners/<slug>/past-events.json, one pair per partner listed in
partners.json. Each file is a JSON object with the same envelope shape:
| Field | Description |
|---|---|
generated_at | ISO 8601 UTC timestamp of when this file was written. |
partner_slug | The same slug as this partner's partners.json entry. |
kind | Either "current" (in events.json) or "past" (in past-events.json). |
event_count | Number of records in the events array below. |
events | Array of event records — see the full field reference below. |
current and past are a true partition, not an
independent filter: every event this pipeline has ever recorded for a partner lands in
exactly one of the two files (undated records included, in past-events.json)
— nothing is silently dropped.
Event field reference
Every event record in events carries exactly these fields (the site's
canonical schema, export.writer.SITE_SCHEMA_FIELDS):
| Field | Description |
|---|---|
slug | string — Stable identifier for this event, unique within the partner's event files. |
title | string — Event title, with HTML entities already decoded. |
partner_name | string — Display name of the hosting partner organization. |
partner_id | integer or null — Numeric id matching this partner's entry in partners.json; null if unmatched. |
description | string — Event description as scraped from the partner source. May contain Markdown syntax and/or unescaped HTML entities (e.g. …) — this site decodes and renders it at build time; a generic client should do the same before display. |
link | string — Canonical URL for the event (its registration link, or its source URL). |
availability | string — Human-readable note: a recurrence summary (e.g. "Repeats 3 times through 2026-05-01"), an application-deadline/rolling note for Work-based Learning listings, or "" when neither applies. |
date_start | string — ISO 8601 start date/time, or "" if unknown. |
date_end | string — ISO 8601 end date/time (or, for Work-based Learning records, the application deadline), or "" if unset. |
age_grade_level | array of strings — Controlled-vocabulary age/grade tags. |
cost_range | string — Controlled-vocabulary cost bucket (e.g. "Free"). |
time_of_day | array of strings — Controlled-vocabulary time-of-day tags derived from the start time. |
opportunity_type | string — LLM-classified category (e.g. "Camp", "Work-based Learning", "Out-of-school Programs"). |
areas_of_interest | array of strings — Controlled-vocabulary STEM subject-area tags. |
specific_attention | array of strings — Reserved for population-targeting tags; always [] in the current pipeline. |
financial_support | string — Reserved financial-aid flag; always "No" in the current pipeline. |
ngss_aligned | string — Reserved NGSS-alignment flag; always "No" in the current pipeline. |
location | string — Event location, falling back to the partner's own address when the event doesn't specify one. |
latitude | string — Latitude (falling back to the partner's), or "" if neither is known. |
longitude | string — Longitude (falling back to the partner's), or "" if neither is known. |
contact_name | string — Reserved; always "" in the current pipeline. |
contact_email | string — Reserved; always "" in the current pipeline. |
contact_phone | string — Reserved; always "" in the current pipeline. |
logo_src | string — Partner logo filename, self-hosted and already downloaded (never a remote URL), or "" if absent. |
eligibility | string — Free-text restriction note (e.g. "Open only to partner high schools") for programs with a closed enrollment pipeline, sourced from the registry, or "" when the program is open/unrestricted. |
image_src | string — Event image filename, self-hosted and already downloaded (never a remote URL), or "" if absent. |
File 3: the robot teams directory — teams.json
Served at /data/teams.json (sprint 017). A single JSON object, independent
of Files 1–2 above: a self-describing meta envelope wrapping a
teams array — the FIRST/VEX robotics teams directory for San Diego County.
No other data source is needed to interpret it.
| Field | Description |
|---|---|
meta.generated | ISO 8601 UTC timestamp of when this file was written. |
meta.total | Number of records in the teams array below. |
meta.by_league | Object mapping each league code ("FTC", "FRC", "FLL", "VEX") present this run to its team count. |
meta.by_location_precision | Object mapping each location_precision value present this run to its team count. |
meta.out_of_region | Number of teams with in_region: false — outside San Diego County, but never dropped. |
Every element of teams carries exactly these fields (the site's canonical
team schema, teams.export.TEAMS_SCHEMA_FIELDS):
| Field | Description |
|---|---|
team_id | string — Stable identifier, {league}-{number} (e.g. "ftc-1622"); league-prefixed so teams from different leagues sharing a number stay distinct. |
league | string — Program code: "FTC", "FRC", "FLL", or "VEX". |
program | string — Human-readable program name (e.g. "FIRST Tech Challenge"). |
number | string — Team number/designation as issued by the league; alphanumeric for VEX (e.g. "90210A"). |
name | string — Team's display name. |
organization | string — Sponsoring school or organization name. |
org_type | string — What organization names: "school", "family_community", or "unknown". |
city | string — City name, from acquisition-time source data. |
postal_code | string — Postal/ZIP code, from acquisition-time source data. |
latitude | number or null — Geocoded latitude, or null if not yet geocoded. |
longitude | number or null — Geocoded longitude, or null if not yet geocoded. |
location_precision | string — Which geocoding rung produced the coordinates: "school", "zip", "city", or "none" if ungeocoded. |
in_region | boolean — false for a team located outside San Diego County (still included, never dropped). |
matched_name | string — The real-world place name the geocoder actually matched (e.g. "St. Pius X School"); empty when location_precision is "none". |
needs_review | boolean — true when a fuzzy school-name match scored below the confidence threshold and should be human-verified. |
website | string — Team's own website, when known, or "" if unknown. |
website_status | string — Liveness-check result for website, or "" if not checked. |
organization_website | string — The matched school's own website (school-precision matches only); distinct from website, never presented as the team's own site. |
social | array of strings — Team-declared social media URLs (Instagram, YouTube, etc.), raw with no platform label. |
rookie_year | integer or null — First season the team competed. |
active | boolean — Whether the team is currently active. |
last_season | integer or null — Most recent season the team competed. |
sponsors | array of strings — Sponsor organization names. |
sponsor_provenance | object — Maps each sponsors entry to how it was found: "structured" (a source's own API) or "scraped" (extracted from a fetched page). |
org_key | string — Cross-league identity key linking sibling teams fielded by the same organization. |
sibling_team_ids | array of strings — team_ids of other teams sharing this team's org_key. |
A trimmed teams.json entry:
{
"team_id": "ftc-1622",
"league": "FTC",
"program": "FIRST Tech Challenge",
"number": "1622",
"name": "Example Robotics",
"organization": "Example High School",
"org_type": "school",
"city": "San Diego",
"postal_code": "92101",
"latitude": 32.7157,
"longitude": -117.1611,
"location_precision": "school",
"in_region": true,
"matched_name": "Example High School",
"needs_review": false,
"website": "",
"website_status": "",
"organization_website": "",
"social": [],
"rookie_year": 2015,
"active": true,
"last_season": 2025,
"sponsors": ["Example Robotics Boosters"],
"sponsor_provenance": {"Example Robotics Boosters": "structured"},
"org_key": "",
"sibling_team_ids": []
}
Worked example
A trimmed partners.json entry for a hypothetical partner, and its matching
events.json — hand-authored, not fetched, to illustrate the shape (Design
Rationale D3: these files may not exist yet in every checkout).
Trimmed entry from partners.json
{
"generated_at": "2026-08-27T12:00:00Z",
"partner_count": 1,
"partners": [
{
"id": 42,
"name": "Example STEM Center",
"organization_type": "Museum",
"location": "1234 Discovery Way, San Diego, CA 92101",
"latitude": 32.7157,
"longitude": -117.1611,
"website": "https://example-stem-center.org/",
"logo_src": "example-stem-center.png",
"slug": "example-stem-center",
"events_url": "partners/example-stem-center/events.json",
"past_events_url": "partners/example-stem-center/past-events.json"
}
]
} Matching partners/example-stem-center/events.json
{
"generated_at": "2026-08-27T12:00:00Z",
"partner_slug": "example-stem-center",
"kind": "current",
"event_count": 1,
"events": [
{
"slug": "family-robotics-night_20260915",
"title": "Family Robotics Night",
"partner_name": "Example STEM Center",
"partner_id": 42,
"description": "Build and race simple robots together as a family.",
"link": "https://example-stem-center.org/events/robotics-night",
"availability": "",
"date_start": "2026-09-15T18:00:00-07:00",
"date_end": "2026-09-15T20:00:00-07:00",
"age_grade_level": ["Elementary", "Middle School"],
"cost_range": "Free",
"time_of_day": ["Evening"],
"opportunity_type": "Out-of-school Programs",
"areas_of_interest": ["Technology", "Engineering"],
"specific_attention": [],
"financial_support": "No",
"ngss_aligned": "No",
"location": "1234 Discovery Way, San Diego, CA 92101",
"latitude": "32.7157",
"longitude": "-117.1611",
"contact_name": "",
"contact_email": "",
"contact_phone": "",
"logo_src": "example-stem-center.png",
"eligibility": "",
"image_src": ""
}
]
} This same contract is what powers the site you're already looking at — browse the Partner Directory to see it rendered.