Direct answer
Put a boundary of your own between your feature and their API, build against that boundary, and learn about the real API early with a small spike (a short, throwaway experiment). Your team then progresses on everything that does not depend on the unstable part, the risky integration is tackled first in its smallest form, and drift is detected by an automated daily check instead of by users.
Structured elaboration
Decouple. Define an interface owned by your team that describes what your feature needs (for example: estimate shipping for a cart, returning minimum days, maximum days and price). Your business logic and screens depend on that interface only. An adapter (a thin translation layer) maps their API to your interface, so a change on their side breaks one file, not the feature.
Split the work
- Spike on the real API. One or two days calling it for real: which fields exist, how errors look, how often it changes. Cheapest way to retire the biggest uncertainty.
- Interface plus a fake. A fake implementation with recorded sample responses lets everyone build and test without waiting.
- Own logic and UI. Fully independent of their stability.
- Adapter to the real API. Small, isolated.
- Drift detection. A scheduled contract check: a test, written by you, that asserts only the fields and behaviors you depend on, run daily against their test environment.
- Resilience. Timeouts, retries with waiting between attempts, a circuit breaker (stop calling a failing service for a short time), and a fallback behavior when it is down.
- Rollout behind a feature flag, so you can turn the feature off without a deploy.
Sequence the risky parts. Spike first, interface and fake second, so risk shrinks before the bulk of the work. Integration with the real API is scheduled early, not last, so surprises arrive while there is time.
Talk to the other team. Ask for a versioned contract, a channel for breaking-change notices and a stable test environment. Escalate with evidence (a log of unannounced changes) if the pattern continues.
Worked example
Feature: show a delivery estimate at checkout using the logistics team's estimate endpoint, which has twice renamed fields without notice.
- Day 1-2: spike shows the price field is sometimes a number and sometimes a string.
- Day 3: interface "estimate(cart)" and a fake with three recorded cases, including an error.
- Days 4-8: checkout UI and logic built against the fake; adapter written and tested with the recorded real responses.
- Day 9: daily contract check enabled; feature flag at 5% of traffic.
When the field is renamed again, the contract check fails the next morning and one adapter line changes. The check runs daily, so the check can take up to a day to notice the rename, plus however long the one-line fix takes to ship, so the exposed window can be longer than a day; during it the resilience layer (timeouts and a fallback such as "usually 3 to 5 days") keeps checkout working and the flag lets you switch the estimate off. The check also runs against their test environment, so it only catches changes that reach that environment first; if production changes first, the adapter's own validation of each live response (log it and fall back when a field is missing or the wrong type) is what protects users.
Trade-offs and pitfalls
- Do not wait for the other team to stabilize; but do not silently absorb every change either, since your adapter can hide a problem they should fix.
- Fakes drift from reality; the contract check exists to catch exactly that.
- A fallback has a product cost (an estimate that says "usually 3 to 5 days" instead of an exact one), so agree it with product in advance.
- What would flip the plan: if they plan to deprecate the API, invest less in the adapter and ask whether a different source is available. If the API is truly unusable, consider keeping your own copy of the needed data.