API Integration Delivery With Unknowns
A practical playbook for converting API integration uncertainty into a verified contract, thin vertical slice, failure model, reconciliation path, and evidence-based...
trigger="A delivery depends on an external or internal API whose documentation, sandbox behavior, rate limits, data quality, error semantics, ownership, or production access is incomplete." owner="One integration lead who can make technical trade-offs, paired with one product owner who can decide what the business should do when the provider cannot complete the requested action." timebox="Ten working days to prove one risky vertical slice and replace the initial unknowns with evidence. Repeat for another slice only when it introduces a materially different failure boundary." participants={["Integration lead", "Product owner", "Provider or source-system owner", "Application engineering", "Security", "Test engineering", "Operations or support", "Data owner"]} prerequisites={[ "One named business event, such as create order, verify identity, reserve inventory, synchronize account, or publish shipment.", "A provider contact or documented escalation route, plus approved credentials for the safest available environment.", "Agreement that unresolved behavior will be recorded as an assumption and tested, not hidden inside an estimate." ]} outputs={[ "A versioned integration contract with examples, field authority, authentication, limits, errors, and compatibility rules.", "An unknowns register with owner, consequence, test, evidence, decision date, and fallback.", "One observable, idempotent thin slice through the real boundary or a representative stub.", "A failure and reconciliation model covering timeout, duplicate, delay, partial success, rejection, and provider outage.", "A delivery plan based on verified facts, bounded assumptions, and explicit client or provider dependencies." ]} doneWhen={[ "The same contract examples pass against the stub, consumer, and available provider environment.", "Repeating the selected command cannot create an unapproved duplicate business effect.", "A timeout produces a recoverable unknown state rather than an invented success or failure.", "Operations can trace one business operation across systems and close a deliberately created discrepancy.", "The remaining estimate names every assumption that can still change scope, sequence, cost, or acceptance." ]} />
Begin with one business event
An API integration is not the endpoint list in a provider document. It is the agreement between two operating systems about a business event, its identity, its authority, and what happens when neither side knows whether the event completed.
Choose one event with a visible consequence. “Synchronize customer data” is too broad. “Create a customer account after an accepted application” is bounded enough to test. Name the initiating actor, required input, authoritative result, maximum acceptable delay, duplicate consequence, and the person who handles an exception.
Write the success in business language before discussing transport. For an inventory reservation, success might mean that one buyer has an unexpired claim to one version of an item and every selling channel sees that claim within an agreed interval. A 200 OK response does not prove that result. A queued response might still be valid if the product can show pending state and reconcile it later.
Record exclusions. Historical migration, bulk synchronization, administrative correction, analytics replication, and normal transactional flow often have different safety properties. Combining them in one “integration” estimate hides work and produces the wrong retry behavior.
Exit gate: the group can describe one event, one authoritative outcome, one maximum uncertainty window, and one unacceptable duplicate effect.
Day 1: build the contract ledger
Create one version-controlled record with the contract facts that delivery will rely on. Link the relevant OpenAPI Specification document when the interface uses OpenAPI, but do not treat the schema as the complete contract. The specification itself notes that schemas cannot detect every violation.
Use the JSON Schema specification when the payload contract needs reusable structural and validation rules. Keep business invariants beside the schema because a structurally valid request can still violate ownership, timing, balance, or state-transition rules.
For each operation record:
| Area | Required evidence | Question it answers | | --- | --- | --- | | identity | base URL, environment, operation, version | which interface are we calling? | | authentication | flow, scopes, token lifetime, rotation | how is access granted and removed? | | request | schema, examples, invariants, size limits | what can be sent? | | response | success, rejection, async acceptance, headers | what does each response prove? | | business identity | operation key, entity key, version | how are retries and conflicts recognized? | | authority | field owner and update direction | which system wins? | | limits | quota, burst, concurrency, pagination | how does load change behavior? | | failure | timeout, error code, partial effect, webhook | what can be known after failure? | | compatibility | additive and breaking change policy | how can either side evolve safely? | | support | owner, hours, severity, escalation | who acts when the contract fails? |
Store representative examples beside the schema. Include a normal success, minimum valid input, maximum-size input, duplicate command, stale version, invalid authorization, business rejection, provider error, and accepted-but-not-completed response.
Do not normalize ambiguous provider words. “Created” might mean persisted, queued, approved, or visible in another system. Ask what evidence exists for each interpretation and write the answer.
Day 1: create the unknowns register
An unknown is useful when it has a consequence and a test. “Webhook unclear” is not actionable. “The provider may deliver the same payment event more than once, which could create two ledger entries; test by replaying the same signed event five times” can be owned and closed.
Use these fields:
| Field | Purpose | | --- | --- | | unknown | the exact behavior not yet verified | | affected outcome | the user, money, data, or operation at risk | | current assumption | the temporary belief used for design | | confidence | observed, documented, reported, or guessed | | test | the smallest action that can produce evidence | | owner | person responsible for obtaining or deciding | | due date | latest safe decision point | | fallback | behavior if evidence does not arrive | | impact | scope, design, sequence, cost, or acceptance change |
Review the register daily during the proof. Close an item only with a link to evidence or a recorded product decision. A provider email can be evidence, but it is weaker than a repeatable sandbox test and should be labelled accordingly.
Escalate unknowns that affect irreversible effects, regulated data, contractual availability, settlement, or customer promises before implementation expands. The team can defer a cosmetic response field. It should not defer whether a timed-out request can still charge a customer.
Day 2: map authority and data movement
For every field, decide whether it is mastered by the source, mastered by the consumer, jointly derived, or copied for reference. Do not use “two-way sync” as a design. Two systems cannot both own the same mutable fact without a conflict rule.
Record the entity identifier, provider identifier, local identifier, external version, last observed time, last accepted time, source, and reconciliation status. Preserve provider references even when the local product exposes a friendlier identifier. They are needed during support and recovery.
Separate commands from observations. “Set shipment delivered” asks another system to perform an effect. “Shipment delivered at 14:03 with provider event 981” records evidence. Recovery may replay observations. It must not casually replay effect-producing commands.
Define how deletion, revocation, and redaction move across the boundary. A downstream cache, search index, file store, analytics table, and support export can retain data after the primary record changes. The data map should include these derived copies and their removal or retention rule.
Day 3: establish a truthful provider double
Use the real sandbox when it demonstrates production semantics. When it is unavailable, unstable, or missing failure controls, create a contract stub. The stub is not a toy success responder. It should validate required headers and schema, return documented errors, enforce representative limits, delay responses, drop a response after accepting a request, repeat events, reorder events, and expose inspection state.
Keep stub behavior traceable to a contract example or labelled assumption. A convenient invented behavior can make the consumer pass while the real integration fails.
Run provider-supplied examples against the stub and consumer-supplied requests against the provider environment. Differences become contract issues, not local patches. If the provider accepts undocumented fields or formats, do not depend on that tolerance unless it is confirmed as supported behavior.
Test credentials separately from application logic. Prove token acquisition, expiry, rejected scope, rotation, clock skew, and revocation. For OAuth integrations, record the exact grant and security profile against the OAuth 2.0 Security Best Current Practice rather than copying an old provider example without review. Keep secrets out of fixtures and captured traffic. Use synthetic identities and minimize any production-derived data.
Exit gate: the team can reproduce the riskiest known provider behavior without waiting for a production incident.
Days 4 to 6: build one thin vertical slice
The slice should cross the real product boundary: user or source event, validation, durable intent, provider interaction, result handling, product state, telemetry, and support view. It should be small enough to discard if a major assumption fails.
Persist intent before an external effect. Give every operation a stable business identifier and attempt history. A network timeout after the provider receives the request leaves the outcome unknown. The system should retain that state and reconcile it, not convert it to failure and submit another command.
RFC 9110 defines idempotent HTTP methods by intended server effect, but an integration still needs domain-level duplicate protection. A POST that creates a charge, reservation, or message requires an idempotency key or another provider-supported mechanism. The local system must also reject conflicting reuse of the same key.
Use bounded retries. Retry only errors known to be transient, with exponential delay, jitter, maximum attempts, and a deadline shorter than the business expiry. Respect provider retry headers. Do not retry validation, authorization, or business rejection as if they were outages.
Capture operation identifier, correlation identifier, provider request identifier, entity version, attempt number, latency, result class, next action, and safe-to-log fields. Never put secrets or unnecessary personal data in logs.
Day 6: define error semantics the product can use
Map transport and provider errors into a small internal result model. Useful result classes include completed, accepted and pending, rejected by business rule, invalid request, unauthorized, rate limited, unavailable, outcome unknown, and manual review required.
Keep the provider code and response reference for diagnosis. Do not expose raw provider wording as the only user message. Product behavior should follow the internal class. A pending result might show progress and prevent another action. A rejection might allow correction. An unknown outcome should block a conflicting command until reconciliation or expiry.
Define the owner and allowed action for every class. If “manual review required” exists but no queue, service target, evidence view, or permission exists, it is not a recovery path.
Model partial success explicitly. A provider might create the remote object but fail to attach a document, publish an event, or return the reference. Decide whether the product can continue, compensate, retry the missing sub-step, or must stop. Avoid a single boolean status for multi-step effects.
Day 7: rehearse failure and reconciliation
Run at least these scenarios through the slice:
- The request fails before leaving the consumer.
- The provider accepts the request but the response is lost.
- The same command is sent twice.
- A success event arrives twice.
- Events arrive out of order.
- The provider returns a business rejection after async acceptance.
- The rate limit activates during a burst.
- The provider is unavailable beyond the retry window.
- Local persistence succeeds but projection or notification fails.
- A mapping is missing or points to the wrong entity version.
For each case, record the durable state, visible user state, allowed next action, retry owner, reconciliation source, alert condition, and final evidence. Reconciliation should compare authoritative records by operation identifier and time window, classify discrepancies, apply idempotent corrections, and retain the before and after state.
Do not close a discrepancy because the screen “looks right.” Confirm the source, provider, local record, downstream projection, and any money or inventory ledger affected by the operation.
Day 8: test compatibility and change
Contract tests should verify examples at the consumer boundary and provider boundary. Additive schema changes can still break a consumer that rejects unknown enum values, assumes field order, or deserializes into a closed model. Test unknown optional fields, new enum values, missing optional fields, larger values, and pagination boundaries.
Pin the contract or provider version used by the release. Monitor deprecation dates and new versions. Assign an owner for reviewing changes. A version header does not help if no one knows when support ends.
For webhooks, verify signature, timestamp tolerance, key rotation, duplicate delivery, delayed delivery, invalid body, and replay. A valid signature proves the sender possessed the signing secret. It does not prove the event has not already been applied.
Review object-level and function-level authorization against the OWASP API Security Top 10. Contract tests should use two identities with different ownership and role boundaries. A successful request with the intended account does not prove another account cannot address the same object identifier.
For file or batch interfaces, define file identity, complete-upload signal, delimiter and encoding, maximum size, row rejection, partial acceptance, duplicate file, replay, and reconciliation totals. A batch is still an integration contract.
Day 9: convert evidence into a delivery plan
Split the remaining work by operational capability, not by endpoint count. A capability includes contract, persistence, security, failure handling, reconciliation, observability, support action, tests, release, and acceptance evidence.
Classify work as verified, bounded assumption, provider dependency, product decision, or later option. Estimate a range where uncertainty remains. State which event would invalidate the range. Keep client and provider dependencies visible with owners and required dates.
Sequence the highest-consequence uncertainty early. Authentication, authority, irreversible effects, rate limits, and unknown outcomes should be proven before low-risk mapping work. If an assumption cannot be tested before commitment, define a discovery stage with a bounded output rather than pretending the build estimate is precise.
Record stop conditions. Examples include the provider cannot support duplicate protection for a financial command, no authoritative lookup exists after a timeout, production credentials cannot be segregated, or a required data field cannot be lawfully transferred. A stop condition protects the outcome from schedule pressure.
Day 10: run the acceptance review
The reviewer should be able to start with one business operation and follow it through intent, provider request, provider evidence, local state, downstream effect, and support action. Demonstrate success plus one unknown-outcome recovery. Show the exact contract version and unknowns register used for the release.
Accept only the slice that has evidence. Do not let a successful demonstration imply that bulk behavior, historical migration, every provider operation, or production scale is complete.
Use this checklist:
"One business event, outcome, authority, expiry, and duplicate consequence are written plainly.", "The contract ledger includes examples, authentication, limits, errors, compatibility, and support ownership.", "Every material unknown has an owner, test, fallback, due date, and consequence.", "The thin slice persists intent before an external effect and carries one stable operation identity.", "Idempotency and duplicate event handling are tested, not assumed.", "Timeout produces an unknown state with reconciliation rather than an unsafe retry.", "Rate limiting, delayed response, out-of-order event, rejection, and provider outage have been rehearsed.", "Logs and traces contain correlation evidence without exposing secrets or unnecessary personal data.", "Operations can find and correct a discrepancy through a product control with retained evidence.", "The delivery plan separates verified scope, assumptions, provider dependencies, decisions, and stop conditions." ]} />
Failure modes that invalidate acceptance
Reject the slice when a duplicate command can produce a second charge, reservation, message, or account. Reject it when a timeout is shown as failed even though the provider may have completed the action. Reject it when reconciliation depends on editing a database row without a controlled action and retained reason.
Return the contract when source authority is disputed, examples contradict the schema, or provider behavior differs from the documented version. Pause expansion when production rate limits, identity scopes, data residency, or support obligations remain unknown and can change the architecture.
Roll back the integration release when observed error rate, duplicate prevention, reconciliation age, or critical journey latency crosses its pre-agreed threshold. If rollback would remove visibility into already-started operations, isolate new requests, keep the worker or reconciler running, and finish existing operations safely.
The useful output is not confidence that the provider will always behave. It is a system that remains truthful when the provider is slow, duplicated, unavailable, or uncertain.
Operating cadence after the first release
Review contract changes, provider incidents, rate-limit use, retry volume, unknown-outcome age, reconciliation discrepancies, manual corrections, and support escalations at an agreed cadence. Track trends by operation and provider version.
Retire assumptions when evidence arrives. Add newly observed behavior to the contract examples and failure suite. Rehearse credential rotation and provider outage before the current runbook becomes stale.
The next action is to select one consequential business event and complete the contract ledger and unknowns register before estimating the whole integration.