A repair network wants to open its booking API to three clients. A public website creates appointments, a shared tablet lets desk staff confirm them, and a partner script synchronizes results overnight. The website deploys weekly, the tablet changes once a quarter, and the partner can only upgrade during a scheduled maintenance window. A successful unit test in the API repository will not show whether the tablet understands a new status or whether the sync script accidentally reads another station's bookings. Give each client a concrete contract, run its real workflow in a test environment, and ship documentation generated from the version that passed.
Start with the decisions the interface must express
List the resources, actors, and actions before writing endpoints. A booking belongs to a station. A visitor can create a booking and read their own result. A desk operator can confirm a booking for their station. A partner can read a limited view of records within its assigned scope. For each action, write down the required state, the request, the success result, and the meaningful ways it can fail. Review this short matrix with a person who operates each client.
For creation, the request includes a station, a slot, and an equipment category. The response identifies the resulting booking and its initial status. Define the semantics of a client-supplied retry key separately from the generated booking ID. In the sample contract, repeating the same key and payload returns the existing booking. Reusing the key for a different slot yields a conflict. Agree on which client and station own the key, how long the service recognizes it, and what happens if an earlier attempt is still in progress. These choices affect both duplicate writes and the message a visitor sees after a slow connection.
Write down each field's type, unit, required status, null behavior, and an example. Use explicit time zones in appointment timestamps and define whether a window includes its closing instant. Give errors stable machine-readable codes and a request identifier. Describe which failures a caller can recover from by changing the input, waiting, signing in again, or contacting a station operator. Define how a canceled booking appears in the sync feed and whether an operator can restore it. Specify whether a page cursor remains valid after changing the filters. Keep unresolved questions next to the example they affect and assign an owner.
Run a contract review with three fictional records. Create one through the website, confirm one on the tablet, and synchronize a page through the partner script. Sketch the exact request and response at each step. Check that the client can determine its next action from what it actually receives. An API design skill can propose field structures and examples, and a contract checker can flag omissions. Give them the draft, the actor matrix, and the expected artifact. Review decisions about permissions and behavior with the people who own them. Preserve accepted decisions in the contract instead of leaving them in a chat transcript.
Find the consumers before changing what they depend on
Build a consumer inventory that names deployed versions, endpoints, fields, release windows, owners, and rollback options. The website may understand new states quickly, while the old tablet may map an unfamiliar state to an empty row. A nightly script may stop parsing a page when it sees a new response field. Treat these as hypotheses and replay requests through the actual client builds. Write each compatibility finding against the client and version that produced it.
Suppose the service adds a waiting for equipment status. Test the old tablet with a response that includes it. Observe whether it renders a fallback label, hides the booking, or fails. If the client cannot migrate in time, keep a compatible representation on the old interface and add the detail to the new one. Document what information the older representation loses and which clients must migrate before it can retire. Review changes in state values separately from changes in pagination so that a later missing record can be attributed to the right behavior.
Compare contracts for removed endpoints, required inputs, enum values, and response changes. Also test defaults that a structural comparison may miss. For example, keeping the same response shape while switching an unfiltered sync from all changes to today's changes would silently lose overnight records. Add a regression case for requests that omit the filter. Replay the same test against the old and proposed implementations and compare the result count, order, and state. Add a page boundary fixture with two bookings at the same timestamp. The next page must contain the expected remaining record without repeating the last item from the previous page.
Test authorization and retry behavior in isolation
Prepare two fictional stations with similar record names and distinct IDs. Give the test runner credentials for a visitor, a station operator, and a read-only partner. First prove each role can complete one allowed action. Then change only the station or record identifier and check the same operation against a record owned by the other station. The visitor should not be able to confirm another person's booking, and the partner should not be able to create one. After a denied request, check that the stored state is unchanged and that the response did not expose details of the other record. Retain the error code and request ID without recording the credential.
Test missing credentials, expired credentials, and valid credentials with insufficient scope separately. Verify the response contract and the client's actual recovery behavior. A tablet that prompts its operator to sign in again for every authorization failure may obscure a missing station assignment. Use separate fixtures for role and resource ownership so that a negative test can reveal which check failed. Reset fixture state between runs, including slot capacity and pending bookings.
For the retry scenario, have the server accept the creation request while a controlled proxy drops the response. Observe whether the website reuses the same retry key after reconnecting. The API response should identify the original booking and the backend should contain one active record. Run a second case in which the first request never reaches the server. The same retry should now create the booking. Run a third case where the client changes the slot but keeps the key and check the conflict response. Test simultaneous submissions for the final slot and verify both the final capacity and the two responses. Capture evidence from the API layer and the client because each observes a different part of the sequence.
Give a test generation skill the contract, role matrix, environment restrictions, and synthetic fixtures. Ask for a case ID, setup, caller, request, expected response, and expected stored state for each case. Review assertions for sensitive operations before running them. A status code can show a request was rejected, while a state assertion shows the rejected request did not mutate a booking. Point the runner at an approved test service. Keep test secrets in the agreed credential store, and record the role and request ID in shared reports.
Make consumer acceptance a release gate
Run one complete journey through all three clients on the candidate build. Create a booking on the website, confirm it on the tablet, and observe the final state through the partner sync. Repeat the workflows with the deployed tablet version and the previous partner script. Attach evidence for each client and record any unresolved differences. If a new feature is unavailable on an old client, state how the old path behaves and who has approved that outcome.
Define stop conditions before routing traffic to the candidate. Examples include a duplicated reservation, a missing page in the partner feed, and a tablet that cannot display the current queue. Keep the previous route and a tested way to restore it. A code rollback may still leave records written with a new status in the datastore. Test how the old version reads those records and decide whether the new state requires a compatible view, controlled write rollout, or a data recovery step. Rehearse that sequence on synthetic data and record who can run it.
During one rehearsal the partner script misses the second of two bookings with equal timestamps. Save the requests, returned cursor, and observed order. Reduce the fixture to the two records and reproduce the gap. After the fix, verify the cursor walks both records exactly once. Then replay the old script's pagination and the new script's synchronization boundary. Update the contract to describe the ordering guarantee and include a fixture that will catch a regression after the next change. The release note should identify which contract version provides the corrected behavior.
Publish documentation from the accepted contract
Generate endpoint tables, types, and response definitions from the versioned description used in testing. Add a short first request, the minimum required credential scope, pagination behavior, and recovery guidance for common errors. Give each example synthetic values. Run the examples against the approved test service and compare the observed response with the contract. If a response in the guide is intentionally shortened, label what was omitted. A documentation skill can organize explanations and examples once the contract owners have confirmed the behavior.
Ship the contract version, runnable examples, consumer test results, and migration notes together. Explain what a consumer must change, when the new behavior becomes available, and how to return to the supported old path. Check the published documentation after rollout to make sure the displayed version is the one that passed. If a public example fails, distinguish a stale example from an authorization or service defect. Correct the responsible artifact and regenerate affected documentation so the same mistake does not return on the next build.
Choose skills by the evidence they produce
Search the catalog for the specific task or use a verified discovery skill in the agent. For design, look for contract output that a reviewer can inspect and compare. For testing, check whether the skill can read the chosen format, express negative authorization cases, and target an isolated service. For delivery, check that the tool can render examples from the exact versioned description. Verify the upstream location, prerequisites, expected changes, and supported formats before installing a candidate. Test all candidates against the same small contract containing an omitted error response and an intentionally ambiguous authorization rule. Prefer an output that clearly separates proposed edits from observed findings.
Common questions
How do I add a contract to an API already in use?
Collect representative requests from each consumer and replay them in a controlled environment. Compare actual responses with existing documentation and code. Ask owners to decide which observed behaviors are commitments and which are bugs. Put the agreed results in the first versioned description and attach examples that reproduce them.
Does schema validation prove that a release is compatible?
It checks the structural expectations encoded in the schema. Client tests exercise decisions around unknown states, default filters, retries, and permissions. Use both sets of evidence and include the rollback rehearsal before accepting a change that writes new state.
What belongs in a client-facing error?
Give clients a stable code, an actionable recovery path when one exists, and a request identifier. Keep operational detail in authorized logs. A slot conflict can suggest choosing another time. An out-of-scope resource request must follow the agreed rejection behavior without exposing the booking's contents. For the website consumer, use the associated Webapp Testing skill during browser acceptance. Provide an approved test address, synthetic accounts, and the expected booking, error, and recovery screens. Capture a screenshot and reproduction steps for failures. Use independent API assertions for stored record counts.