Data Mapping Overview
This document provides an overview of how the WeGive donor platform maps to Planning Center’s People and Giving modules. The real mapping is narrower than a generic CRM sync — a handful of fields per object, no custom fields, no household/family sync, and no recurring-gift sync.Object Mapping Categories
The integration maps objects across two Planning Center modules:- People Module — Person, plus embedded email/phone/address contact info
- Giving Module — Donation, Batch, Fund, PaymentSource, Designation
There is no Planning Center RecurringGift sync in this integration —
pushTransaction() (the only place a Transaction touches the API) is a literal no-op; Planning Center recurring gifts are only ever read incidentally as a correlation reference on pulled donations, never pushed or independently synced.Core Object Mappings
People Module Mapping
Giving Module Mapping
Planning Center Object Details
Person Object
Fields actually synced:first_name,last_name(falls back to literal"FNU"/"LNU"if blank on push)- Up to 3 emails (position-based:
email_1/email_2/email_3) - Up to 2 phone numbers (position-based:
mobile_phone/office_phone) - One mailing address
status(pulled only, maps to the donor’senabledflag)
There’s no birthdate, anniversary, gender, middle-name-on-pull, suffix, or household/family-relationship mapping. Middle name is pushed but not pulled back.
Donation Object
Fields actually synced:amount_cents,payment_method(cardorach, from the transaction’ssource_type),received_at/created_at,person_id- Exactly one
Designation(fund + amount) per donation — split/multi-fund gifts aren’t supported
Batch Object
description— the batch’s own display name, formatWeGive Import MM/DD/YYYY- Batches are found-or-created once per push run (one batch per day, not one per donation) and auto-committed after processing
Fund Object
Fields actually synced:name(push and pull),description(push on create only, pull),visibility(push always setseverywhere; pull’shiddenvalue soft-deletes the WeGive fund)color_identifieris set to a fixed value of1on create, never read back
No fund goal amount, category, hierarchy/parent-child structure,
is_active/active-status sync, or analytics fields are mapped — WeGive’s funds.active column exists but isn’t pushed to or read from Planning Center at all.PaymentSource Object
A single Planning Center payment source named “WeGive” is found or created once and reused for every transaction — there’s no per-payment-method or per-organization payment source.WeGive Object Mappings
Donor ↔ Person
Transaction ↔ Donation
Push side note: a pulled donation whose transaction has a
correlation_id (WeGive-processed payment) or is still future-dated-pending keeps its WeGive-owned amount/allocations — a Planning Center-side edit doesn’t overwrite the real payment amount (this is a guarded, fixed behavior, not an open issue).
Fund ↔ Fund
Data Synchronization Rules
Correlation ID Management
planning_center_idis the only matching mechanism, on every object type (Donor, Fund, Transaction)- There is no email-based or name-based matching fallback anywhere in this integration
- A push targeting a
planning_center_idthat returns 404 (record deleted externally) clears the stale ID and creates a new record instead of failing
Sync Direction Rules
Push (WeGive → Planning Center): creates or updates byplanning_center_id; existing Planning Center Person/Donation records are updated on push, but an existing Fund match is left untouched after initial creation (no update path).
Pull (Planning Center → WeGive): creates or updates WeGive records by planning_center_id; pull always overwrites the local record’s mapped fields, with the one carve-out above for transactions already owned by a WeGive-processed payment.
API Endpoint Reference
Planning Center API Endpoints Actually Used
people/v2/people, and per-person nested emails/phone_numbers/addresses (via theinsert/updatehelper methods)giving/v2/batches,giving/v2/donations,giving/v2/payment_sources,giving/v2/funds
There is no
giving/v2/recurring_gifts write path used by this integration — recurring gifts are only referenced as a read-only relationship ID on a pulled donation.Integration Notes
Data Validation
- Planning Center requires a name — WeGive substitutes
"FNU"/"LNU"placeholders rather than failing when both first and last name are blank - A transaction with a non-positive amount is silently skipped on push (Planning Center requires positive amounts)
- A transaction that can’t resolve any fund (no fund link, no
default_fund_id, no fallback fund) throwsUnknown Fund Sourceand is skipped — logged to Sentry, not surfaced to the customer
Performance Considerations
- Transactions sync exclusively through the once-daily 8:01 AM batch job — there’s no real-time transaction push
- Donor and fund pushes happen in real time as part of the batch build (
pushDonor()/pushFund()called inline per transaction) - Pulls (donors, funds, transactions) run on a separate once-daily schedule with no fixed time
- API calls are throttled to Planning Center’s real limit (70 requests / 20 seconds) via a hardcoded internal counter, not a configurable setting
Related Documentation
Known Gaps (not implemented)
- Household/family relationship sync
- Recurring/scheduled-gift sync
- Custom fields
- Multi-fund/split-designation support
- Fund goal, category, hierarchy, or activity-status sync
- Performance/monitoring telemetry of any kind