/v1/ segment in the base URL (https://api.vomo.org/v1). A v2 overhaul will eventually arrive, addressing many of the audit-flagged quirks (type inconsistencies, naming inconsistencies, anonymous schemas) accumulated in v1. When that happens, integrations that handled v1’s quirks defensively will migrate gracefully; integrations that depended on v1’s exact behavior will break.
This page covers the patterns that prepare integrations for API evolution: defensive parsing, version-aware clients, feature flags for behavior changes, deprecation handling, and the partner-side schema evolution practices that keep integrations running through inevitable change.
The eventual v2 reality
The current v1 API has documented quirks that v2 will likely address:
These are documented in the audit findings throughout the docs (see Concepts and individual workflow pages). Many integrations have built workarounds for them; v2 will allow those workarounds to be removed.
But between now and v2, your integration runs against v1. And during the transition, your integration may need to support both. This page is about how.
Principle 1: defensive parsing at every boundary
The single most valuable practice for surviving API evolution: never trust the API’s response shape. Parse defensively at the boundary; produce a clean internal representation; quarantine the API’s quirks in one place.The pattern
JavaScript
hours as a string or number.
When v2 ships
JavaScript
Principle 2: version-aware clients
Plan for v1 and v2 to coexist during the transition. Use a version-aware client that knows about both:JavaScript
Per-customer version selection
For staged migration, version selection becomes per-customer:JavaScript
Principle 3: ignore unknown fields
When the API returns fields you don’t recognize, ignore them. Don’t fail; don’t log them as errors; just skip:JavaScript
last_login_at), your integration continues working — it just doesn’t surface the new field until you decide to. This is the forward-compatible reading principle: be conservative in what you send, liberal in what you accept.
Don’t fail on additions
The wrong thing to do:JavaScript
Optional: log unknown fields for awareness
For debugging help (during v2 transition especially), log unknown fields at a low level:JavaScript
Principle 4: feature flags for API behavior changes
When migrating from v1 to v2 (or any time you change how the integration handles API responses), wrap the change in a feature flag:JavaScript
At each phase, monitor: error rates, processed-record counts, reconciliation gap rates. If anything degrades, roll back the flag (no code deploy needed).
Principle 5: schema evolution on the partner side
Your own data model evolves too — fields get added, types change, columns are deprecated. Plan for the partner-side schema to evolve in lockstep with VOMO’s changes:Pattern: additive changes only
Whenever possible, add columns; don’t remove them. Removing a column breaks queries that depend on it.Pattern: nullable new columns
New columns should be nullable initially:NOT NULL. Or accept nullable forever — sometimes the right answer.
Pattern: schema versioning
For complex schemas, track the migration version:Principle 6: deprecation handling
When VOMO eventually marks a field or endpoint as deprecated (typical pattern:Deprecation header or Sunset header per RFC 8594), your integration should:
- Detect the deprecation in API responses
- Log it for awareness
- Schedule migration before the sunset date
- Verify the migration before the sunset takes effect
Pattern: detect deprecation headers
JavaScript
Pattern: scheduled migration with safety margin
For a deprecated endpoint with a sunset date, migrate well before:
If you wait until the last 30 days, you’re under pressure and prone to bugs. Earlier migration leaves room to handle surprises.
Principle 7: contract testing
For partner integrations, run regular tests against VOMO that verify the integration’s assumptions about response shapes:JavaScript
- Nightly against the production API (with a test customer’s token)
- As part of CI for any release that touches the integration
expect(typeof hours === 'number') would now pass without the string fallback. You’d see the change immediately and could plan the migration.
Don’t test in production with real data
Use a dedicated test customer / test organization for contract tests. Don’t run them against a real customer’s data — both for privacy and for stability (test runs could affect real data if the API behaves unexpectedly).Principle 8: graceful handling of schema differences
Your integration’s schema and the API’s schema will inevitably diverge. Build the partner side to accommodate either:Pattern: optional source fields
If a downstream system requires a field that VOMO sometimes returns as null:JavaScript
Pattern: rejection vs. degradation
For records that can’t be sanely processed (missing required fields, malformed data), choose between rejection (DLQ) and degradation (process with defaults):JavaScript
Principle 9: documentation of assumptions
Every assumption your integration makes about the API should be documented. When the API changes, the documentation tells you what to re-verify. A simple convention: a per-integrationAPI_ASSUMPTIONS.md file:
Principle 10: graceful failure modes for API changes
When the API does something unexpected, what does your integration do?
The general principle: fail loudly enough to be detected, but quietly enough to not crash the whole integration. Per-record failures go to DLQ; systemic patterns trigger alerts; the integration continues serving the customers it can.
Migration playbook for v2
When VOMO v2 lands, the migration follows a predictable pattern:Phase 1: assess (week 0-2)
- Review v2’s changes against
API_ASSUMPTIONS.md - Categorize: backward-compatible additions, type fixes, structural changes
- Estimate effort per category
Phase 2: prepare (week 2-6)
- Update the parser layer to handle both v1 and v2 response shapes
- Add feature flag for v2 client selection per customer
- Update contract tests to verify v2 shapes
- Run contract tests against v2 with a test customer
Phase 3: pilot (week 6-8)
- Migrate internal test customer to v2
- Run for 1-2 weeks
- Monitor: error rates, reconciliation gaps, processing rates
Phase 4: progressive rollout (week 8-20)
- 1 friendly customer → 10% → 50% → 100%
- At each step, monitor metrics for ~1 week before advancing
Phase 5: cleanup (week 20+)
- Remove v1 code paths
- Update
API_ASSUMPTIONS.md - Update documentation
- Celebrate
What’s worth defending against vs. accepting
Not every potential API change deserves defensive code. The pragmatic decision matrix:
The general rule: defend against subtle changes that could silently produce wrong output; accept the cost of explicit migration for major changes that are obvious when they happen.
Final principle: design for change
The deepest defense against API evolution is making the integration easy to change. Practices that support this:
An integration with these practices doesn’t dread API changes — it absorbs them. An integration without them treats every change as a crisis. The difference is months of cumulative engineering work, paid out one improvement at a time.
Where to go next
Sync Architecture Patterns
The architectural patterns that make change manageable.
Security and Credential Management
The security patterns that complement versioning hygiene.
Data Modeling
The data model that allows partner-side schema evolution.
Error Recovery Patterns
The error-handling patterns that absorb API changes gracefully.