Skip to main content

Integration Nuances

This page previously contained a large amount of generic, non-code-verified filler (rate-limit throttling, exponential-backoff retry, webhook queuing, rollback tooling, escalation tiers, and more) that doesn’t reflect what this integration actually does. It’s been rewritten around verified behavior only.

Account Creation and Duplicate Prevention

  • Account type: determined by the WeGive donor’s type field (individual or company) — sent to Neon as IndividualAccount/CompanyAccount accordingly
  • Duplicate prevention on push: neon_account_id correlation only. There’s no name+address secondary matching. exportDonor() does have one specific fallback: if creating a new account fails with Neon’s error code 10012 (duplicate account), the integration searches Neon by email and links the existing account rather than creating a second one — but that’s the only “duplicate resolution” logic that exists.
  • Duplicate prevention on pull: email match against existing WeGive User records — a Neon account row missing an email is skipped entirely, not partially imported

Transaction Synchronization

  • Create vs. update: a transaction with both neon_id and neon_payment_id already set triggers an update call; otherwise it’s treated as new and creates. There’s no restriction against updating an existing Neon donation — the “payments not modified” framing in a prior version of this page was inaccurate.
  • Fee attribution: donorCoveredFee is only sent as a non-zero value when the transaction has cover_fees set — otherwise 0
  • Received date: payout.paid_at maps to Neon’s receivedDate, but only once the transaction has an associated payout (i.e., after it’s actually been paid out, not at initial gift creation)

Custom Field Mapping Behavior

The literal mapping-rule flag is not honored by Neon’s field-application code — every configured mapping is resolved as a JSONPath lookup against rendered WeGive data, regardless of the flag. This is a known issue, with a fix in review.
Field mappings are push-only in practice. NeonMappingRule records are only consulted by the push (export) functions — generateAccountParams()/generateDonationParams(). Pull uses its own separate, hardcoded field list and never applies NeonMappingRule at all. A mapping rule configured with level = 'import' or 'both' has no pull-side consumer. This is a known issue.
  • JSONPath resolution: $.path.to.field syntax against a pre-rendered resource array (via DonorWebhookResource/TransactionWebhookResource), not a live model traversal
  • Array handling: the mapping code takes the first element of whatever JSONPath returns (->get(...)[0])
  • No type coercion or automatic conversion: whatever value the JSONPath resolves to is sent as-is

Campaign Integration

  • Active/inactive filtering on pull: importCampaigns() explicitly skips any Neon campaign with status == 'INACTIVE'
  • Statistics are pull-only, computed by Neon, never by WeGive: total_donated, number_of_donations, etc. are read from Neon’s own statistics object — WeGive doesn’t calculate these independently
  • No campaign hierarchy, event, or custom-field support: campaign push sends name, dates, goal, status, and generated donation/checkout URLs only

Address Management

Address sync (syncAddress()) is dead code — it never actually runs. It’s fully implemented but has no caller anywhere in the codebase. This is a known issue.
  • What would happen if it were wired up: push-only, one-way WeGive → Neon, with mobile/office/home/fax phone fields included alongside address fields — but this is describing unreachable code, not current behavior
  • What actually syncs today: the donor account push (generateAccountParams()) includes both mailing and — for individual donors only — billing address, whenever both exist, with no “only primary address” filtering. This inline copy has no phone/fax fields — meaning no phone or fax data reaches Neon via this integration at all today.
  • No format/state-code/zip validation performed by WeGive in either path: whatever’s stored in the WeGive address record would be sent as-is

Payment Method Handling

Only 3 WeGive payment source types are mapped: card → Credit Card Offline, bank/donor → Check, anything else → Check (fallback default). There is no distinct cash, stock/securities, in-kind, or “other methods” categorization — despite this being listed as flexible in prior documentation.
  • Card data: only the last 4 digits (zero-padded to 4 characters if shorter), issuer (mapped to a single-letter code — Visa/MasterCard/Amex/Discover only), and expiration month/year are sent — full card numbers are never transmitted by this integration
  • Bank data: institution name, account type (always "Checking"), and last 4 digits — same zero-padding logic as cards

Error Handling

There is no automatic retry, exponential backoff, or rollback tooling anywhere in this integration. Every Neon API call (get/post/put/remove on NeonIntegration) is a single Http::timeout(120) request. A failed call simply fails; the calling code either returns early/skips (donor/campaign/address sync) or throws an exception that propagates up (pushTransaction/pushScheduledDonation in Neon.php explicitly throw on a failed response).
  • Donor sync failure blocking donation sync: if syncDonation() needs to create a Neon account first (donor has no neon_account_id) and that donor export fails to actually assign one, syncDonation() throws an explicit exception rather than silently skipping the donation
  • Webhook delivery failures: WeGive is the receiver for the 4 supported webhooks (donor/donation create/update), not the sender — retry behavior for a failed webhook delivery is entirely Neon’s responsibility, not something this integration configures or monitors

Integration Limitations

  • No event/ticketing sync
  • No volunteer tracking sync
  • No communication/email history sync
  • No file attachment sync
  • No campaign hierarchy sync
  • No address sync at all — this is a known issue; phone/fax numbers never reach Neon via any path in this integration
  • Webhooks limited to donor and donation create/update — no webhook exists for recurring donations, campaigns, or addresses
  • track_donations/track_recurring_donations toggles are dead — this is a known issue; only track_donors (all donor-adjacent objects) and track_campaigns actually gate sync

Troubleshooting

Sync Failures

  • Check Sentry (not a dedicated dashboard) for the specific integration log/error
  • Verify both the Neon Organization ID and API key are correct
  • If a donation isn’t syncing, check whether the donor sync (triggered inline first) failed

Data Looks Wrong in Neon

  • Payment method showing as Check unexpectedly: expected for any source type other than card — see the payment method warning above
  • Custom field not populating on pull: known gap — pull doesn’t apply NeonMappingRule at all
  • A “literal” mapping rule not sending its fixed value: known gap, in review

Support and Escalation

For specific field-level detail, see the Data Mapping Overview.