crmKey — determine whether the data tells a coherent story years later. Partner integrations are often the first place where these structural decisions show up as friction: a reporting integration that can’t find the gift it expects, a sync that produces duplicate donors, an analytics dashboard that can’t slice by the dimension the customer wants.
This page covers the modeling patterns that produce clean Raise data and the decisions to make explicitly during integration onboarding rather than discovering later.
The audience is partner integration leads helping a customer think through their Raise setup, and partner engineering teams whose integrations depend on the data shape being predictable.
The five modeling decisions that matter most
In rough order of impact on integration design:
The next sections walk through each.
Decision 1: donor matching
The most consequential modeling decision: how donors are identified and matched across submissions.Email is the de facto primary key
Raise’s donor-matching algorithm — embedded inPOST /api/Raise/give and in donor lookups — primarily matches on email. The implications:
- Donors with the same email collapse into one record. When a donor gives twice and uses the same email both times, both gifts attach to one Donor.
- Donors who change emails effectively become new donors. A donor who gave as
bruce@wayne.examplelast year and gives asbruce.wayne@updated.examplethis year will produce two distinct Donor records unless the integration explicitly reconciles them. - Donors who use a household email shared with a partner can produce ambiguous matches. “Bruce and Selina Wayne” giving from a shared email may produce one donor record that represents both — or different records if the form captures both names.
Practices that handle these cases well
For partner integrations interacting with donor records:
For partner integrations creating new donors via submissions, don’t try to outsmart the matching by uniquifying email addresses with suffixes — the resulting fragmentation is harder to fix later than the duplicate issue you were trying to avoid.
Organization vs. individual donors
TheisOrganization flag distinguishes a corporate or foundation donor from an individual. Set it correctly at submission time:
JavaScript
organizationName is set, or an organization whose firstName is “Wayne” and lastName is “Foundation”) produces messy reporting and odd-looking thank-you emails.
Decision 2: Campaign and Segment structure
Campaigns and Segments are how the customer reports on revenue by appeal, channel, and time period. The structure determines whether reports answer the questions the customer actually asks.The hierarchy
- Campaign = the umbrella effort (e.g., “2025 Annual Appeal”, “Capital Campaign Phase 2”)
- Segment = the channel or wave within a campaign (e.g., “Email — Q1 2025”, “Direct Mail — March”)
- Form = the specific donation form (e.g., “Annual Appeal Online Form”, “Donor Renewal Form”)
- All gifts to the 2025 Annual Appeal (campaign level)
- All gifts driven by email in Q1 2025 (segment level)
- All gifts from a specific form (form level)
Practices for designing the hierarchy
Anti-pattern: segments as Projects
A common mistake: using Segments as a substitute for Projects (designations). Segments are about how the donor came in; Projects are about what the donor funded. Don’t conflate them — a gift to the “General Fund” Project that arrived through the “Email Q1” Segment can answer both “how much did email drive?” and “how much went to general operations?” Separately, you get clean intersections.Working with the structure in partner integrations
When reading gifts for analytics, the attribution fields onGiftModel provide direct access:
JavaScript
Decision 3: Project taxonomy
Projects represent the funding destinations gifts designate to. The taxonomy — what Projects exist, how granular they are, how they evolve over time — determines what reports the customer can produce.Two opposing pressures
The right answer is in between, and customer-specific.
Practices for Project taxonomy
Project codes vs. names
Each Project has both a name (display) and a code (stable identifier used inprojectOverrideCode URL parameters and similar). The code should:
- Be short and code-like (
GOTHAM-OUTREACH, notGotham Outreach Program 2025). - Be stable across the Project’s lifetime — don’t rename it as the program evolves.
- Be unique across the organization.
projectOverrideCode=OLD-CODE breaks. Treat codes as part of the integration’s public contract.
Working with Projects in partner integrations
For analytics integrations, the project allocation is ingift.projects[]:
JavaScript
projects[] array on a 100.
Decision 4: Custom Fields
Custom Fields capture data that doesn’t fit the standard schema — donor preferences, gift-time questions, organizational metadata. Used well, they add dimensions to reporting and integration logic. Used poorly, they become a junk drawer of inconsistent values.Practices for Custom Field design
Working with Custom Fields in partner integrations
For reading Custom Field values on a Donor:cURL
cURL
Don’t use Custom Fields for everything
A common anti-pattern: treating Custom Fields as the universal extensibility mechanism for every integration’s needs. A partner integration that creates 50 Custom Fields on every customer’s account pollutes the customer’s data model — the customer sees these in their admin UI and has no idea what they’re for. For partner-internal state (sync metadata, processing flags), keep the data in your own database. Use Custom Fields only when:- The data is meaningful to the customer’s reporting or staff workflow.
- The customer would benefit from seeing the field in the Raise admin UI.
- The data belongs to the donor or gift, not to the integration.
Decision 5: CRM key seeding
For customers running Raise alongside CRM+ (or another external CRM), thecrmKey, crmSecondKey, and crmKeyUrls fields link Raise records to their counterparts in the external system. See How Raise Data Flows to CRM+.
The decision: when (if ever) should the partner integration seed these values explicitly versus letting the platform sync populate them?
When to seed crmKey explicitly
When not to seed
Reading vs. writing crmKey
Reading crmKey is always useful — it tells the partner integration whether the record has been synced and which external Contact it links to. Writing crmKey only matters when the partner has authoritative knowledge of the linkage.
JavaScript
Test mode and production separation
Throughout the data model,isTestMode flags appear on submissions, donors, gifts, and recurring gifts. Treat test mode as a first-class data axis:
Partner integrations should also filter
isTestMode: true records out of downstream syncs unless explicitly running in a development environment. See Sync Raise Gifts to an External System: Test-mode in production.
Modeling pitfalls to avoid
A few specific anti-patterns that produce messy data:Pitfall 1: one Project for everything
Every gift designating to “General Fund” produces a single revenue line in reports. The customer can’t slice by program, can’t show donors what their gift funded specifically, can’t distinguish unrestricted from restricted giving. Add at minimum 5–10 Projects to cover the major programs.Pitfall 2: a Campaign per appeal
The opposite problem: every email blast is a new Campaign. Hundreds of Campaigns accumulate, most with a few gifts each, and the “all campaigns” view becomes unreadable. Use Segments for sub-divisions; reserve Campaigns for the major efforts.Pitfall 3: Custom Fields as a junk drawer
A customer accumulates 50+ Custom Fields over the years, most with inconsistent values, half of them used by integrations that no longer exist. Periodically audit Custom Fields and archive the ones that aren’t actively used.Pitfall 4: not setting isOrganization
A foundation giving $50,000 with isOrganization: false and firstName: "Wayne" lastName: "Foundation" looks weird in reports and breaks any logic that filters individual vs. organizational donors. Always set the flag correctly.
Pitfall 5: using free-text where a Project would do
“What did the donor designate to?” captured in a free-text Custom Field rather than as a Project allocation produces unstructured data. Use Projects for designation; Custom Fields for the things that genuinely don’t fit standard fields.Pitfall 6: keeping test-mode donors in production reports
A common reporting issue: the customer’s “all donors” count includes hundreds of test-mode records from development work. FilterisTestMode: false everywhere production-facing.
Onboarding a new customer
For partner integrations onboarding a new customer, walk through these decisions together:1
Audit the customer's existing data shape
How many Campaigns? Segments? Projects? Are the conventions consistent? Are there orphaned Custom Fields?
2
Document the canonical taxonomy
Write down what Campaigns and Projects exist, what they mean, and what new ones should be added. This becomes the integration’s contract.
3
Set the integration's expectations
“Our integration filters out test-mode gifts.” “Our integration assumes Projects have stable codes.” Make implicit expectations explicit.
4
Plan for Custom Field needs
If the integration needs Custom Fields, propose them with clear names and types — and confirm the customer wants them in their data model.
5
Coordinate on `crmKey` policy
If the customer also runs CRM+, agree on who’s responsible for what — the partner integration may or may not need to seed linkage data.
6
Document and revisit annually
The data model evolves. Revisit the taxonomy decisions at least once a year to catch drift.
Where to go next
API Performance Tips
The performance practices that make integrations against this data model efficient.
Sync Architecture Patterns
How to design integrations that move data between Raise and external systems.
How Raise Data Flows to CRM+
The cross-product implications of the modeling decisions on this page.
The Raise Data Model
The resource-level reference for the data the modeling decisions apply to.