Skip to content

Latest commit

 

History

41 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

UniSchema

CI License: MIT Node DOI

v0.4.2 — Open-source webhook unification for university advancement & nonprofit fundraising teams.

UniSchema normalizes fragmented advancement webhooks into ConstituentEvent; PhilanthroPy scores propensity, lapse, and engagement on the features you build from that stream.

Pilot-ready, not production-hardened. Eight built-in vendors, SQLite or Postgres, self-hosted.
Read docs/limitations-and-roadmap.md before production donor data.

One URL: API + admin UI on the same port.

UniSchema mapping canvas — visually map vendor webhook fields onto the ConstituentEvent master schema


Who it's for

  • Advancement analytics teams ingesting 2–4 webhook vendors (GiveCampus, Cvent, Slate, NPSP, etc.)
  • Shops that want a single normalized event stream for warehouse, dashboards, or ML
  • Teams comfortable self-hosting Node + secrets + S3 (or local egress for pilots)

Not for (today): a fully managed SaaS with vendor SLAs (UniSchema is self-host only) · bi-directional CRM sync (this is webhook ingest + normalize, not a CRM) · fully no-code vendor onboarding (new vendors need a one-time code deploy — see canvas vs code) · orgs whose constituent model differs significantly from ConstituentEvent (use normalizedMetadata or fork via RFC).


Ecosystem

flowchart LR
  Vendors[VendorWebhooks] --> UniSchema[UniSchema]
  UniSchema --> Egress[LocalOrS3Egress]
  Egress --> Features[FeatureTable]
  Features --> PhilanthroPy[PhilanthroPy]
  Features --> CRM[CRMGoldenRecord]
  CRM --> PhilanthroPy
  PhilanthroPy --> Scores[AffinityAndLapseScores]
Loading
Project Role
UniSchema (this repo) Ingest webhooks → validate → map → egress ConstituentEvent
PhilanthroPy sklearn-native ML for advancement (RFM, propensity, lapse)
dbt / Airflow (optional) Warehouse staging and orchestration — downstream guide

Full stack map → docs/ecosystem.md

The ConstituentEvent contract is published as a versioned JSON Schema — schema/constituent-event.schema.json — so downstream consumers validate against a fixed artifact instead of hand-copied field names. Regenerate with npm run schema:export; a drift test fails CI if it falls out of sync with the Zod schema.


Quick start (~15 minutes)

Requires: Docker + Docker Compose, plus curl and jq for the demo scripts (python3 for the downstream demo).

git clone https://github.com/PhilanthroPy-Project/UniSchema.git
cd UniSchema
docker compose up --build
  1. Open http://localhost:3000 — mapping canvas + API together
  2. In another terminal: bash scripts/demo-webhook.sh (single webhook) or bash scripts/demo-webhook.sh --multi (all vendors)
  3. See ConstituentEvent JSON under data/egress/
  4. Prove downstream value: bash scripts/downstream-demo.sh (needs python3)
GiveCampus POST → 202 Accepted → background map → data/egress/.../eventId.json
Without Docker
npm install          # also installs the frontend workspace
npm run build
SERVE_FRONTEND=true npm start   # long-running — leave this in its own terminal
npm run demo:multi              # then run this in a second terminal

Choose your guide

I am… Start here
New adopter — first webhook in ~15 min Quick start above
Admin / analyst — drawing mapping lines on the canvas docs/admin-guide.md
Operator — secrets, S3 egress, cloud deploy docs/operator-guide.md
Developer — adding vendor #9 docs/adding-a-vendor.md
Data engineer — warehouse + dbt docs/downstream-pipeline.md
Data scientist / ML engineer — PhilanthroPy scoring docs/philanthropy-integration.md
All docs docs/README.md

Canvas vs code (what needs a deploy)

The visual mapper overrides fields on registered vendors — it does not create new webhook routes.

Task Canvas Requires deploy
Remap fields → normalizedMetadata Yes No
Override built-in field wiring Yes No
New POST /webhooks/{vendor} route No Yes (6-file checklist)
HMAC secret + Zod payload schema No Yes

Details → docs/canvas-vs-code.md


Maturity & limits

Stage Stack Throughput (typical) Guide
Pilot (~15 min) Docker + SQLite + local egress ~600–900 req/min (Docker, limit raised) Quick start
Production Fly/Railway + S3 + Postgres optional ~120 req/min/IP default; tune for giving day Operator guide
Scale Postgres + Redis + multi-instance Benchmark before peak — npm run benchmark Benchmarks
Today (v0.4.2) Limits
8 vendors: GiveCampus, Cvent, iModules, Blackbaud, NPSP, Slate, Ellucian, CiviCRM Tier 3 — verify with real payloads
Tier 1: GiveCampus, Cvent · Tier 2: iModules · Tier 3: Blackbaud, NPSP, Slate, Ellucian, CiviCRM Ellucian + CiviCRM are bootstrap Tier 3
SQLite default + optional Postgres Horizontal scale needs Postgres + Redis
HMAC webhook verification ~120 req/min/IP default
Visual canvas + metadata mappings Opinionated master schema — details
Local + S3 egress → PhilanthroPy ML bridge ML requires optional pip install -r examples/downstream/requirements-philanthropy.txt
Drift queue + experimental LLM agent Human review requiredai-agent-loop
3 event types: registration, donation, email click New types via RFC — schema-governance

Vendor registry (8 built-in) → docs/README.md#vendor-registry


Downstream and ML

After npm run downstream-demo:

pip install -r examples/downstream/requirements-philanthropy.txt
python3 examples/downstream/philanthropy_crm_pipeline.py data/egress samples/crm-golden-record.csv

Citing

If you use UniSchema in academic or applied fundraising-analytics work, cite the release you used — a CITATION.cff ships with the repo, so GitHub shows a Cite this repository button in the sidebar. Every tagged release is archived on Zenodo with a citable DOI.


API (summary)

Method Path Description
GET /health Health check (version, egress, driftPendingCount)
GET /api/vendors Vendor registry with tier metadata
POST /webhooks/{vendor} Vendor webhooks (202)
GET /webhooks/ingestions/:id Poll async status (Bearer auth in production)
POST /api/mappings/sync Save canvas mapping (Bearer auth in production)
POST /api/mappings/preview Preview ConstituentEvent from artifact
GET /api/mappings/:vendor Load canvas mapping
GET /api/drift/events Schema drift queue

Admin routes are also available without the /api prefix. Local dev works without tokens when NODE_ENV is not production.

Full operator reference → docs/operator-guide.md.


Project layout

UniSchema/
├── src/                    # Hono API — mappers, egress, drift
├── frontend/               # React mapping canvas
├── tests/                  # Vitest unit + integration
├── docs/                   # Role guides + PhilanthroPy integration
├── examples/downstream/    # Analytics, dbt, PhilanthroPy pipelines
├── deploy/                 # Fly.io, Railway, Terraform
├── samples/                # Demo webhook payloads
├── scripts/                # demo-webhook.sh, benchmarks
└── agents/                 # Experimental drift agent (Python)

Testing

npm test                  # backend
npm run validate          # full CI parity (backend + frontend + build)

Cloud deploy

Deploy on Fly.io Deploy on Railway

Docker image: ghcr.io/PhilanthroPy-Project/unischema:0.4.2

Platform Docs
Fly.io deploy/fly.toml + deploy/README.md
Railway deploy/railway.toml
Any host Dockerfile

Minimum production env vars.env.example and operator guide.


License

MIT

About

Normalize fragmented advancement & nonprofit-fundraising webhooks (GiveCampus, Cvent, Slate, NPSP, Blackbaud…) into one Zod-validated ConstituentEvent stream. TypeScript + Hono, self-hosted. Pairs with PhilanthroPy.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages