/api/{Resource}/... — no /v1/, no /v2/. This isn’t an oversight; it’s the platform’s current shape, and partner integrations should design around it.
This page covers what the unversioned namespace means for partner integrations, the defensive coding patterns that handle change gracefully, what to expect from future API evolution, and the practical work that keeps an integration durable across years of platform development.
The audience is integration architects making long-term durability decisions and engineers writing the code that will be running against Raise five years from now.
The unversioned reality
Every Raise API path begins with/api/:
/v1/, no /v2/. The implications:
| Implication | What it means |
|---|---|
| Changes apply to all clients at once | When Raise updates an endpoint’s behavior, every integration sees the change simultaneously. No “stay on v1 until you’re ready” option. |
| Breaking changes are platform-level decisions | If a field is renamed, every integration must adapt. The platform team coordinates this carefully. |
| New fields appear without integration code changes | Additive changes to response shapes don’t break clients that ignore unknown fields. |
| Defensive coding is non-optional | An integration that assumes the spec it was built against is the spec forever will eventually break. |
What the OpenAPI spec actually represents
The Raise OpenAPI spec is the platform’s documented contract, but it’s not always identical to the live API’s behavior. A few realities partner integrations should understand:The spec lags the live API
Spec updates lag platform changes. A new field added to a response may take weeks to appear in the spec; a new endpoint may exist in production before it’s documented. This means the live API is sometimes a superset of what the spec describes. For partner integrations, the implication is don’t blindly trust the spec as exhaustive. Build flexibility for fields and behaviors that the spec doesn’t yet document.The spec sometimes lags the live API in the other direction
Less commonly, the spec may document fields or behaviors that don’t yet exist in production — features that are planned but not deployed. Treat the spec as a contract for what should work, but verify against live data when behaviors are critical.Integer enums often lack labels
Throughout the Raise spec, integer enums appear without labels:QueryOperator, Frequency, EventType, Status, Format, ChargeStatus, and others. The spec exposes the integer set but doesn’t document what each integer means.
This is a documentation gap, not a contract gap — the values are stable. Partner integrations should:
- Discover the integer-to-label mapping through documented discovery paths (e.g.,
eventTypeDisplayonWebhookLogListModel,statusDisplayon various resources,GET /api/Query/options/{queryType}). - Cache the discovered mapping.
- Treat unknown integer values gracefully (don’t crash on a new integer that wasn’t there at integration build time).
Optional fields may be missing
The spec marks some fields as optional. In practice, optional fields can:- Be absent from the response entirely (no key in the JSON).
- Be present with a
nullvalue. - Be present with a default value (often empty string or
0).
JavaScript
Defensive coding patterns
The patterns below make integration code resilient to the changes that will inevitably happen.Pattern 1: ignore unknown fields
When deserializing API responses, ignore fields the integration doesn’t know about. Don’t fail on new fields that appear over time:JavaScript
Pattern 2: handle unknown enum values gracefully
When the integration encounters an integer enum value it doesn’t recognize, log it and continue rather than crashing:JavaScript
JavaScript
Pattern 3: handle new fields opportunistically
When the live API starts returning new fields the integration could use, the integration can adopt them at its own pace:JavaScript
Pattern 4: feature-detect rather than version-detect
Without a version segment to switch on, integrations can’t say “if v2, do this; if v1, do that.” Instead, detect features by what fields or endpoints exist:JavaScript
Pattern 5: defensive deserialization with explicit defaults
Build all integration code to handle missing or null fields explicitly:JavaScript
- Documents which fields the integration uses (everything else is ignored).
- Handles missing fields with sensible defaults.
- Provides a single place to update when the platform changes the shape.
- Catches drift early — if a field that was supposed to be present is missing, the default surfaces rather than crashing.
Monitoring for drift
The defensive patterns handle most changes invisibly. For changes that need attention, monitoring catches them before they cause customer-facing issues.Track unexpected response shapes
Log fields the integration didn’t expect:JavaScript
Track unknown enum values
Same pattern for integer enums:JavaScript
Track unexpected error responses
If the integration suddenly starts seeing400 errors it didn’t see before, that may indicate the API has tightened validation:
JavaScript
400s may mean a payload your integration sends has become invalid — investigate and adapt.
Track null where you expected a value
If a field that’s typically populated starts coming back null frequently, something has changed:JavaScript
When breaking changes do happen
Even with the best intentions, breaking changes occasionally happen — a field is renamed, an endpoint is restructured, an enum value is repurposed. The platform team announces these in advance (typically through release notes, partner email, or admin UI banners). When you see one:Read the announcement carefully
Identify exactly what changes, when it takes effect, and whether there’s a compatibility window.
Inventory your integration's exposure
Which code paths touch the affected resource or field? Search the codebase for the field name, endpoint path, or enum integer.
Build the new behavior alongside the old
Don’t tear out the old code until the new code is tested and verified working.
Test against a staging or developer organization first
If the platform offers a way to opt into the new behavior early, use it.
Roll out gradually
For multi-customer integrations, roll out to a few customers first, monitor, then expand.
A potential future: API versioning
The unversioned namespace is the current state, but it’s possible the platform will introduce explicit versioning at some point. Speculation about what that might look like:| Possible future | Implication |
|---|---|
/v2/api/... prefix introduced | Integrations would need to switch over; both could exist in parallel for a window |
Header-based versioning (Api-Version: 2) | Less URL churn; integrations send the version they expect |
| Both old and new shapes returned in transition | Maximally compatible; old clients work unchanged |
Per-endpoint versioning (/api/v2/Donor/list) | Allows incremental migration |
What /api/ (with no version) actually buys
Despite the lack of explicit versioning, the unversioned namespace has some practical advantages:
| Advantage | Description |
|---|---|
| No version-migration treadmill | Integrations don’t need to plan migrations to keep up with version deprecations |
| Additive changes are free | New fields and endpoints don’t break existing integrations |
| Platform team is incentivized to be careful with breaking changes | The pain of breaking everyone at once means breaking changes are rare |
| Simpler URL patterns | No mental overhead of “what version am I on?” |
A durability checklist
Walk through this when designing the integration:- JSON parsing tolerates fields the integration doesn’t recognize
- Optional-chaining used everywhere for nested field access
- All field reads use
?? defaultValuefor explicit defaults - Unknown enum values logged but don’t crash
- Feature detection used instead of version detection where features vary
- Integration tests run against live API or recent fixtures, not just unit-test mocks
- Drift metrics track unknown fields, unknown enums, unexpected
400s, unexpected null rates - Alerts on drift-metric spikes
- Mappings between integer enums and labels are cached, not hardcoded as if eternal
- Reference data lookups handle the “what if this Project no longer exists?” case
- Webhook payload shape isn’t assumed to be exhaustive — new fields can appear
- Documentation references include the date the integration was built against, so divergence over time is visible
- A regular cadence exists for reviewing the spec for changes (quarterly at minimum)
A final note: durability over cleverness
The single biggest factor in long-term integration health is resisting the temptation to be clever about the platform’s current shape. A “minimal” integration that hardcodes assumptions (“the response always has exactly these 12 fields”, “frequency is always one of these 7 values”, “this enum integer means X forever”) will break repeatedly as the platform evolves. A “defensive” integration that handles missing fields, unknown enums, and unexpected shapes will keep working through years of change. The defensive version is sometimes more verbose. It’s almost always worth the verbosity.Where to go next
Statuses and Lifecycle States
The integer-enum landscape the defensive patterns on this page apply to.
Security and Credential Management
The complementary durability story for credentials.
Error Recovery Patterns
The error-handling patterns that pair with versioning durability.
The Raise Data Model
The current data model — defensive coding makes the integration durable as this evolves.