On this page10 sections
API Contract Review
Review an OpenAPI 3.0 contract for a user-profile microservice before implementation begins — identify schema gaps, undocumented error responses, ambiguous field definitions, and missing acceptance criteria, then produce a test-idea catalogue.
Role
API Tester
Difficulty
IntermediateTime limit
90 min
Category
microservices contract
Scenario
The ShopFlow platform is adding a User Profile microservice. The backend team has shared a draft OpenAPI 3.0 contract for the service and asked the QA team for a structured review before implementation begins. Two consuming services are already planned: the ShopFlow frontend (reads username, email, role, and preferences) and the Orders service (reads userId and role to validate purchase permissions). Your task is to conduct a thorough contract review and produce the deliverables listed below so that the team can improve the contract and bootstrap the test suite before a single line of code is written.
Requirements
- 1.Identify at least eight specific gaps, ambiguities, or risks in the draft contract — classify each as one of: missing field detail, undocumented response, ambiguous type, missing constraint, or design risk
- 2.Write at least five clarifying questions addressed to the correct stakeholder (developer, product owner, or architect) that would unblock test design if answered
- 3.Document at least three acceptance criteria that are implied by the known business rules but not expressed in the contract — state each as a testable condition (e.g. 'POST /users with a duplicate username must return 409 Conflict')
- 4.Produce a test-idea catalogue containing at least six positive test cases and at least six negative or edge-case test cases derived from the contract as-is
- 5.Identify every error response missing from each endpoint and document a proposed status code and a sample error-body structure for each
- 6.Propose at least three concrete, field-level schema improvements referencing the exact component and field (e.g. 'Add format: email and maxLength: 254 to components/schemas/CreateUserRequest/properties/email')
- 7.Summarise the top two or three risk areas in one paragraph, explaining which gaps are most likely to cause integration failures or test-design dead-ends if left unresolved
Starter data
- ›Draft OpenAPI 3.0 contract (abbreviated YAML): openapi: "3.0.3" info: title: User Profile Service version: "1.0" paths: /users/{userId}: get: summary: Retrieve user profile by ID parameters: - name: userId in: path required: true schema: { type: integer } responses: "200": description: OK content: application/json: schema: { $ref: '#/components/schemas/UserProfile' } /users: post: summary: Create a new user profile requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/CreateUserRequest' } responses: "201": { description: Created } components: schemas: UserProfile: type: object properties: id: { type: integer } username: { type: string } email: { type: string } role: { type: string } created_at: { type: string } preferences: { type: object } CreateUserRequest: type: object required: [username, email] properties: username: { type: string } email: { type: string } role: { type: string }
- ›Known business rules (from stakeholder conversation, not yet in the contract): usernames are globally unique and must be 3–30 characters; email must be a valid RFC-5322 address; role must be one of 'customer', 'admin', or 'vendor'; users are never hard-deleted — soft-delete is handled via a 'status' field (not shown in the draft)
- ›Authentication: all endpoints require a Bearer token in the Authorization header — this requirement is not documented anywhere in the draft contract
- ›Consumers: ShopFlow frontend reads all UserProfile fields; Orders service reads only id, username, and role to validate purchase permissions
- ›Planned but absent from this draft: PATCH /users/{userId} for profile updates and GET /users (paginated list) — the team has confirmed they are out of scope for v1.0
Expected deliverables
- ✓A contract gap and ambiguity register: a table or numbered list with each issue classified by type (missing field detail / undocumented response / ambiguous type / missing constraint / design risk) and a one-sentence description of the risk if left unresolved
- ✓A clarifying-questions list: at least five questions, each identifying the stakeholder who can answer it (developer, product owner, or architect) and why answering it is necessary before writing tests
- ✓Missing acceptance criteria: at least three criteria stated as testable conditions with a specific input, endpoint, expected status code, and expected response element
- ✓Test-idea catalogue: at least twelve test cases total (six positive, six negative/edge), each with an ID, scenario description, endpoint + method, input summary, expected status code, and expected response shape
- ✓Missing error responses: for each endpoint, list every undocumented error, propose a status code, and provide a sample JSON error-body structure
- ✓Schema improvement proposals: at least three concrete suggestions in the form 'In component X, field Y: add/change Z to W' — specific enough to apply directly to the YAML
- ✓Risk summary paragraph: top two or three risks with their likely business or integration impact stated
Evaluation rubric
| Dimension | What reviewers look for |
|---|---|
| Gap identification breadth and accuracy | Does the review find gaps at every level — schema-level (missing format, enum, minLength/maxLength, required marker), response-level (missing 400, 401, 404 responses), and design-level (undocumented auth, no soft-delete field, no pagination hint)? A review that only notes 'no examples' without identifying type ambiguities or absent error responses misses the most consequential issues. |
| Clarifying-question quality | Are questions specific and actionable? 'What should role contain?' is weak. 'Should role be constrained to an enum of customer | admin | vendor, and can a user's role change after creation — if so, which endpoint handles the update and what validation applies?' is strong. Questions must unblock a concrete test-design decision, not just express curiosity. |
| Acceptance criteria testability | Are the missing acceptance criteria stated as testable conditions with concrete inputs and expected outcomes? 'Username must be unique' is a requirement, not a criterion. 'POST /users with a username that already exists must return 409 Conflict with response body { code: "USERNAME_TAKEN", field: "username" }' is a testable criterion that can drive both a test case and a contract. |
| Test-idea coverage | Do the test ideas cover both endpoints, include at least one chained scenario (POST then GET to verify the created resource), test each distinct error class separately (400 invalid payload, 401 missing auth, 404 unknown user), and exercise boundary values for constrained fields (username at 2, 3, 30, and 31 characters)? |
| Schema improvement specificity | Are proposals actionable without further clarification? 'Add validation to the email field' is not actionable. 'In CreateUserRequest/properties/email: add format: email and maxLength: 254' is implementable directly. Each proposal must reference the exact schema component and field and state the precise change in OpenAPI terms. |
| Risk prioritisation | Does the risk summary distinguish business-impact risks (the undocumented auth requirement will cause the Orders service to call the endpoint without a token and receive unexpected 401 errors in integration) from low-impact cosmetic gaps (missing example values)? The most critical risks should be ranked by consequence, not by order of discovery. |
Sample solution outline
- ›Gap register (8 entries): (1) email — type: string, no format: email — risk: invalid emails accepted at DB level; (2) role — type: string, no enum — risk: any string value accepted, consumers cannot know valid values; (3) created_at — type: string, no format: date-time — risk: consumers cannot safely parse as timestamp; (4) preferences — type: object, no sub-schema — risk: consumer contract tests cannot generate correct stubs; (5) GET /users/{userId} — no 404 response — risk: consumer error-handling is undefined; (6) POST /users — no 400/422 response — risk: invalid-payload behaviour is undefined; (7) neither endpoint documents authentication — risk: consumers discover the 401 requirement in integration; (8) id: integer, no minimum — risk: 0 or negative IDs are technically valid per the spec
- ›Clarifying questions: (1) To dev: Should role be an enum of customer | admin | vendor? Can it change after creation? (2) To PO: What are the minimum and maximum character lengths for username? (3) To dev: What does the preferences object contain — is its schema versioned or a free-form map? (4) To architect: Is a Bearer token required on both endpoints? Which token format and which auth server issues it? (5) To dev: Is a soft-delete status field planned for v1.0 or a future version? If v1.0, should it appear in the UserProfile response schema?
- ›Missing acceptance criteria: (1) POST /users with a username that is already taken returns 409 Conflict with body { code: 'USERNAME_TAKEN', field: 'username' }; (2) POST /users with an email that is not a valid RFC-5322 address returns 422 Unprocessable Entity with body { code: 'INVALID_FORMAT', field: 'email' }; (3) GET /users/{userId} where userId does not exist returns 404 with body { code: 'NOT_FOUND', resource: 'user' }
- ›Test ideas (positive): GET /users/{id} for a known user → 200 with all schema fields present; POST /users with valid payload → 201 with auto-generated integer id; GET after POST → 200 same data round-trips correctly; POST /users with role 'admin' → 201; GET /users/{id} verifies created_at is a valid ISO-8601 date-time string; POST /users with username exactly 30 characters → 201
- ›Test ideas (negative): GET /users/9999 → 404; GET /users/abc → 400 (non-integer path param); POST /users missing email → 422; POST /users with role 'superuser' → 400 or 422 (if enum enforced); POST /users without Authorization header → 401; POST /users with username 2 characters → 422 (if minLength: 3 is enforced)
- ›Schema improvements: (1) email: add format: email and maxLength: 254 on both UserProfile and CreateUserRequest; (2) role: add enum: [customer, admin, vendor] on both schemas; (3) created_at: add format: date-time and readOnly: true on UserProfile; (4) username: add minLength: 3 and maxLength: 30 on CreateUserRequest; (5) id: add minimum: 1 and readOnly: true on UserProfile; (6) Add securitySchemes: bearerAuth and security: [{bearerAuth: []}] on both operations and document 401 responses
- ›Risk summary: The most critical gap is the undocumented authentication requirement — the Orders service consumer has no basis for including a Bearer token, which means integration will fail with unexpected 401 errors that are not covered by any test case. The second critical risk is the undefined role enum: without known valid values, consumer contract tests will produce incorrect stubs, and the Orders service cannot write role-based permission logic with confidence. Both issues are undiscoverable from the contract alone and will only surface in integration if not resolved before implementation begins.
Common mistakes
- Reviewing only the happy-path schema and missing the complete absence of error responses — the single most impactful gap in this contract is that neither endpoint documents a 404, 400, or 401, yet candidates often focus exclusively on adding format constraints to field types
- Writing clarifying questions like 'Is this correct?' or 'Can you clarify the role field?' instead of questions specific enough to unblock a test-design decision
- Stating acceptance criteria as vague requirements ('email must be valid') rather than testable conditions with a concrete input, endpoint, expected status, and expected response element
- Proposing schema improvements as 'add validation' without specifying the exact OpenAPI keyword, value, and schema component path — a developer cannot act on that
- Omitting authentication from the review because it is not explicitly in the contract — undocumented security requirements are a design risk, not an out-of-scope item
- Generating test ideas beyond the scope of contract-derived functional testing (e.g. load tests, UI tests) — a contract review generates functional test cases from the contract, not a full regression suite
- Failing to identify the preferences: {type: object} ambiguity — an unspecified object is one of the most consequential gaps for consumer contract testing because consumers cannot generate correct interaction stubs
Submission checklist
- Contract gap register with at least eight entries, each classified by type (missing field detail / undocumented response / ambiguous type / missing constraint / design risk)
- At least five clarifying questions, each identifying the correct stakeholder and why the answer is required before writing tests
- At least three missing acceptance criteria stated as testable conditions with status code and response shape
- Test-idea catalogue with at least six positive and six negative/edge test cases, each with ID, endpoint, method, input, expected status, and expected response shape
- Missing error responses documented for every endpoint with proposed status code and sample error-body JSON
- At least three concrete schema improvement proposals referencing the exact component, field, and OpenAPI keyword to change
- Risk summary paragraph with top two or three risks and their business or integration impact stated explicitly
Extension ideas
- +Implement three of your test ideas as a Postman collection against a mock server built from your improved contract, and verify they pass or fail as expected
- +Write a JSON Schema file for the UserProfile response object that enforces all the constraints you identified in your gap register, then validate a sample response against it using ajv or another validator
- +Draft the missing error-response schemas as OpenAPI 3.0 components/responses entries and write a proposed YAML diff for the contract that resolves all eight gaps in your register