> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wegive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Nuances

> Important considerations and behaviors of the WeGive Planning Center integration

# Integration Nuances

This document outlines important behaviors, limitations, and considerations when using the WeGive Planning Center integration, including specific features of the People and Giving modules.

## Authentication Behaviors

### OAuth 2.0 Flow

**Authentication Process:**

* Initial OAuth authorization redirects to Planning Center
* User grants permission for the 'people giving' scope
* Authorization code exchanged for access and refresh tokens

**Token Management:**

* Every API call checks token expiry first; if expired, the access token is refreshed proactively before the call is made
* If the refresh call itself fails (e.g. the refresh token was revoked), it throws — there's no automatic re-authorization flow; a human has to reconnect the integration

### Legacy Authentication

**Basic Auth Process:**

* Uses Application ID and Personal Access Token, sent as HTTP Basic Auth
* Same scope access as OAuth (people and giving)

<Note>
  There's no built-in migration tool between legacy and OAuth authentication — switching means reconfiguring the integration with new credentials.
</Note>

## Data Flow Behaviors

### Daily Batch Processing

**WeGive Import Batches:**

* One scheduled job (`command:generate-planning-center-batches`, daily at 8:01 AM) creates a batch for the previous day's transactions
* Batch name format: `WeGive Import MM/DD/YYYY`
* Every run also does a separate "missing" catch-up batch covering all transactions that still have no `planning_center_id`, regardless of date
* A batch auto-commits after all transactions in it are processed

**Batch Processing Logic:**

* Transactions are selected by `succeeded_at` falling in the target day's range, not any other processing timestamp
* A batch with zero eligible transactions is logged as `ignored`, not created in Planning Center at all
* If `createTransactionsBatch()` throws partway through, the whole batch's changes are rolled back: any `planning_center_id`s set during that run are cleared and the partial batch is deleted in Planning Center
* Pulling (donors, funds, and transactions from Planning Center) runs on a **separate** daily schedule (`command:pull-integrations planning_center`, once per day, no fixed time configured) — it is not tied to the 8:01 AM push job and doesn't run at "8:15 AM"

### Fund Assignment Logic

**Priority Order for Fund Assignment (fixed, not configurable):**

1. **Specific Fund**: Use the fund linked on the WeGive transaction, if it has a `planning_center_id`
2. **Default Fund**: Fall back to the integration's configured `default_fund_id`
3. **Oldest Fund Fallback**: Fall back to the destination organization's oldest fund that has a `planning_center_id`
4. **Skip**: If none resolve, the transaction throws `Unknown Fund Source` and is skipped (reported to Sentry, not a batch failure)

**Fund Visibility Handling:**

* A Planning Center fund whose `visibility` becomes `hidden` is soft-deleted in WeGive automatically on pull
* Fund visibility does **not** sync bidirectionally — when WeGive pushes a fund it always creates it with a fixed `visibility: everywhere`
* Fund push is find-or-create by name only: an existing Planning Center fund is never updated after the initial match/create, so later WeGive-side name/description edits don't propagate

## Contact Management Behaviors

### Person Record Matching

**Matching is `planning_center_id`-only** — there is no email or name-based matching. A donor that hasn't already been linked to a Planning Center person (via a stored `planning_center_id`) will always create a new person record on push, even if a matching person already exists in Planning Center.

**Contact Information Handling:**

* Up to 3 emails (`email_1`/`email_2`/`email_3`) and 2 phone numbers (`mobile_phone`/`office_phone`) are pulled by position, not by any semantic "primary" designation
* One mailing address is synced per contact

### Family and Household Relationships

<Note>
  There's no household/family-relationship sync in this integration — WeGive donors and Planning Center people are synced as independent individual records with no family/household linkage.
</Note>

## Payment Source Management

### WeGive Payment Source

**Single Payment Source Strategy:**

* All WeGive transactions post to a single Planning Center payment source named "WeGive," found by name or created automatically on first use
* The original payment method (card vs. ACH) is sent as the donation's own `payment_method` attribute, not tracked via multiple payment sources

## API Rate Limiting and Performance

### Planning Center API Limits

**Rate Limiting:**

* Planning Center's own limit is 70 requests per 20 seconds
* WeGive's integration proactively throttles to this internally: it sleeps for 20 seconds after every 70th request, rather than waiting for a 429 response

### Large Data Set Handling

* Pull operations for donors, funds, and transactions all paginate through the Planning Center API 100 records at a time
* There's no separate checkpoint/resume system beyond the normal `updated_at`-range pagination

## Error Handling and Recovery

### Automatic Error Recovery

**Retry Logic (GET requests only):**

* GET requests made via the integration's retry-wrapped HTTP client are retried up to 3 times on transient failures (HTTP 408/429/500/502/503/504, or connection-level errors), with exponential backoff honoring a server `Retry-After` header when present
* Mutating requests (POST/PUT/PATCH/DELETE) — creating a donor, fund, or donation — are **not** automatically retried; a failure there is caught and reported to Sentry, not retried

**Batch Error Handling:**

* A single transaction's push failure is caught per-transaction inside the batch loop and reported to Sentry — the loop continues to the next transaction, so one bad transaction doesn't fail the whole batch
* A failure in the batch-level setup (looking up/creating the batch or payment source) fails the entire batch and triggers the rollback described above

### Common Error Scenarios

**Authentication Errors:**

* Token expiration is handled automatically via proactive refresh
* If the refresh token itself is invalid, the batch/pull run fails with an `error-execution` log — there's no automatic re-authentication

**Data Validation Errors:**

* Missing fund resolution (`Unknown Fund Source`) causes that transaction to be skipped, not the whole batch
* Non-positive transaction amounts are silently skipped (Planning Center's API requires positive amounts)

## Sync Timing and Scheduling

### Automated Operations

* **8:01 AM daily**: Push batch generation for the previous day's transactions, plus a missing-transactions catch-up batch
* **Once daily (no fixed time)**: Pull donors/funds/transactions from Planning Center
* There is no continuous/real-time transaction push — `pushTransaction()` is a literal no-op stub; only donor and fund pushes happen in real time (inline, as part of the batch build and elsewhere)

## Fund and Designation Behaviors

### Fund Creation and Management

* A fund push automatically creates the fund in Planning Center if no name match exists — this isn't optional or configurable
* Fund `description` is set on create only; it isn't kept in sync afterward

### Split/Multi-Fund Gifts

<Note>
  Each donation sent to Planning Center includes exactly one fund designation — split gifts across multiple funds aren't supported by this integration.
</Note>

### Recurring Gift Coordination

<Note>
  There's no recurring-gift sync between WeGive scheduled donations and Planning Center recurring gifts in this integration — Planning Center recurring-donation IDs aren't referenced anywhere in `PlanningCenter.php`.
</Note>

## Best Practices

### Data Management

* Monitor `integration_logs` regularly — none of the failure modes above (batch rollback, per-transaction fund-resolution skip, auth failure) surface to the customer-facing dashboard
* Set a valid `default_fund_id` to avoid `Unknown Fund Source` skips
* Link donors to their existing Planning Center person before their first push, if avoiding duplicate contact creation matters

### Troubleshooting Preparation

* Check `integration_logs` (`status = 'error-execution'` for auth/setup failures) and Sentry (`Unknown Fund Source` for per-transaction fund-resolution failures) — these are the only places these failures are visible


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.