/api/ with no version segment, while a specific subset uses /api/v2/. There is no /api/v1/ prefix; the unversioned /api/ paths are effectively v1, and /api/v2/ represents newer or improved implementations on a per-endpoint-family basis.
This page covers what’s known about the model today, which endpoints use /v2/, what backward-compatibility commitments to assume, and how to write integration code that survives the platform’s evolution.
The current versioning state
What’s on /v2/ today
Two endpoint families currently use the /v2/ prefix:
Everything else uses
/api/ with no version segment. The Contact endpoints, the (non-batch, non-v2) Gift endpoints, the Project endpoints, the RecurringGift endpoints, the Webhook endpoints, the Query endpoints for most resources — all unversioned.
Why /v2/ exists
The /v2/ prefix indicates a more recent, sometimes redesigned implementation of an endpoint family. For Gift Transactions, the /v2/ version is the recommended path for partner integrations submitting gifts. For Pledges, the /v2/ family is the only version exposed in the current spec.
This means partner integrations should prefer the /v2/ variant when it exists for the operation they’re performing. There’s no documented reason to call /api/Gift/Transaction (without /v2/) for a new integration. If a non-v2 variant exists for the same operation, treat the /v2/ one as canonical.
Writing code that anticipates /v2/ evolution
Partner integrations have a long lifespan — measured in years. The current /v2/ inventory is unlikely to be the final inventory; new families may be promoted to /v2/ over time, and at some point a /v3/ may appear. Three patterns help:
Pattern 1: configurable base path per endpoint family
Don’t hardcode/api/ or /api/v2/ throughout your codebase. Centralize the path construction:
JavaScript
Pattern 2: feature detection over hardcoded behavior
If two variants of an endpoint exist and the field shapes differ, detect what the platform accepts rather than assuming:JavaScript
Pattern 3: defensive deserialization
Don’t assume response payloads have exactly the fields documented in the spec — they may have extras (added in a non-breaking spec update) or omissions (if a field was deprecated). Parse defensively:JavaScript
Pick<> types if generating from the spec.
Spec-vs-live field typing
A backward-compatibility concern specific to CRM+: the OpenAPI spec types many fields asstring that the live API actually accepts (and sometimes returns) as native types — booleans, integers, dates.
This mismatch is documented in Contacts: field typing, Donations / Gifts: field typing, and elsewhere. The implications for versioning:
- Don’t trust auto-generated SDKs that strictly enforce the spec types. They’ll send
"true"(string) for booleans and rejecttrue(native) in responses, both of which break against the live behavior. - Send native types in requests. They work today and align with what most modern APIs do.
- Parse defensively in responses. If you expect a boolean and get a string, coerce; if you expect an integer and get a string number, parse it.
JavaScript
The spec-vs-live typing mismatch is a known issue documented across the audit findings. The platform may eventually update the spec to match live behavior (or vice versa). Until then, write defensive parsing.⚠️ Human input required: Establish whether the spec or the live API is the canonical source for field types. Either bring the spec in line with live behavior, or document that the spec is the authoritative source and the live API will be aligned to match.
Backward compatibility commitments
Without an explicit versioning policy from the platform team, partner integrations should make conservative assumptions about what may and may not change.What’s safe to assume stable
The following kinds of changes would be backward-breaking and are unlikely to happen silently:What may change without notice
The following kinds of changes are not breaking and partner integrations should expect them to happen:What’s ambiguous
A few changes sit in the middle and require explicit confirmation when they happen:Handling deprecated endpoints
If an endpoint is deprecated in a future version, the platform will typically:- Add a new endpoint that supersedes it (often under a new version prefix like
/v2/or/v3/). - Continue to support the old endpoint for a deprecation window — typically months to years.
- Eventually remove the old endpoint.
Detect deprecation signals
The platform may emit deprecation warnings via response headers or via documentation. Specifically, watch for:JavaScript
Migrate proactively
When a/v2/ (or future-version) variant is introduced for an endpoint family you use, plan migration on a reasonable timeline rather than waiting for sunset:
1
Read the new endpoint's documentation
Confirm what changed — field shapes, semantics, error conditions.
2
Implement against the new variant in a feature-flagged path
Both old and new code paths are present; the flag chooses between them.
3
Test against the Seeded Sandbox
Verify behavior parity between old and new before any customer is migrated.
4
Migrate customers gradually
Per-customer flags let you migrate one customer at a time and roll back if issues surface.
5
Remove the old code path
After all customers have been migrated, delete the old code. Don’t leave dead code paths in the codebase.
Defensive coding checklist
A set of practices that make integration code more resilient to platform evolution:- Endpoint URLs are constants in one place, not hardcoded throughout the codebase.
- Field access is by-name lookup with sensible defaults, not strict shape destructuring.
- Response parsers handle both native and string forms of typed fields (booleans, integers, amounts, dates).
- Webhook event handlers switch on known event types and ignore unknown ones, rather than failing.
- Enum values are not hardcoded for validation — let the API reject invalid values instead of pre-validating against a stale enum list.
- Status code handling is by status class (
2xx,4xx,5xx) for retry logic, with explicit branches for known specific codes (401,404,409,422,429). - Deprecation headers and
Sunsetheaders are logged or metric-counted, not silently ignored. - SDK code generated from the spec is reviewed before adoption — strict implementations break against the spec-vs-live typing differences.
Where to go next
Error Recovery Patterns
The error-handling practices that complement the defensive coding patterns on this page.
Base URLs and Environments
The reference for the host-level URL structure and how
/v2/ paths fit into it.Sync Architecture Patterns
The architectural patterns that the migration approach on this page builds on.
Changelog
The platform’s evolution log — watch for deprecation announcements and new versioned endpoints.