Final assignment
- After the case studies
- about 5 hr
What you will be able to do
Change a real API the way a team does. Agree the contract first, build it and document it. Test it from the inside and the outside, deploy it, and prove that the deployment works. You add one endpoint to your ticket-api project, and you keep evidence of each part.
Before you startWhat to know and to have ready
What you need to know
- You completed Modules 1 to 7. Each part below names the lessons that it uses.
- You do not need the case studies of Module 8 for this assignment. (The certificate asks for at least one of them.) To see a similar change on a real project first, open Serve a house-price model. It adds a batch endpoint, names the item and the field in each error, and changes the body limit to fit the largest valid batch.
What you need on your computer
- Your
ticket-apiproject, as at the end of Verify and clean up: Guided practice: verify and clean up.python -m pytestpasses. - If your project is missing or broken, copy the snapshot
end-of-m07, the project at the end of Module 7. Use a snapshot has the steps. It has no deployed app and no key: Part 6 makes new ones. - The Postman collection runs from the terminal, as in Tests and repeatable runs: Run it from the terminal: the Postman CLI.
- For Part 6, a FastAPI Cloud account, from Publish safely: Step 1: sign in and create the app, or the local deployment simulation from Hosting bridge: Worked example: production mode on your computer.
- You can do the assignment in more than one session. Run the tests after each change.
The situation
Section titled “The situation”The help desk system now sends tickets in groups. Every few minutes, it collects up to 20 new tickets. Then it calls the API once for all of them, instead of 20 times. The help desk lead asks for:
- A batch endpoint.
POST /v1/classify/batch, with a body of 1 to 20 tickets, each one valid as for/v1/classify. The response has one classification for each ticket, in the same order. - The same protections. The API key, the time limit and the body-size limit apply, as for one ticket.
- Clear errors. An empty list, more than 20 tickets, or one invalid ticket gives
422. The error says which field: for the fourth ticket’s subject,tickets.3.subject(the list starts at 0). - No change for existing clients. Everything that works today keeps working, exactly as before.
Rules for every part
Section titled “Rules for every part”- Keep the structure: models in
models.py, the route inroutes.py, the classifier unchanged. - After each change, run
python -m pytest. When the contract test fails, read the difference before you export, as in Keep the documentation true. - No secret in any file: not in the code, not in
postman/, not in your evidence. - Make a file
evidence.mdoutside the project folder, for example~/projects/c16-evidence.md. After each part, copy the outputs that the part asks for into it.
Part 1: the contract first
Section titled “Part 1: the contract first”Uses Resource and endpoint design and Validation and error responses.
- Write the contract table for
POST /v1/classify/batch: the request body, the response body, and a row for every failure. The failures are: no key, empty list, 21 tickets, one invalid ticket, unknown field, the classifier down, and a body that is too large. - Decide the version. Is a new endpoint a breaking change? What is the new
versioninFastAPI(...)? - Calculate: 20 tickets, each with a body of 1,000 characters. Is that request under the 16 KB body limit? Decide what to do about it, and write the decision in the table: change a limit, or document it.
Evidence for part 1: the contract table, the version decision and the size decision, each with one sentence of reason.
Part 2: build it
Section titled “Part 2: build it”Uses Request and response models, Separate concerns and Basic protection.
- Add a model for the request (a list of
TicketIn, from 1 to 20 items, no unknown fields). Also add a model for the response (a list ofClassification). - Add the route. It uses the same classifier dependency, the same API key check, and the same time limit for the whole batch.
- Check by hand: send the example from your contract table with curl or Postman.
Evidence for part 2: the request and the response of one batch of two tickets.
For a batch of {"subject": "Charged twice for March"} and {"subject": "Parcel lost"}, the results are billing and shipping, both with priority 1 and confidence 0.7, in that order.
Part 3: document it
Section titled “Part 3: document it”Uses Documentation people can use and Keep the documentation true.
- Give the route a summary, a description that states the limits and the order of the results, and every documented error response with
ErrorResponse. - Give both models an example that works.
- Run the tests. Read the contract difference: the new endpoint, the new schemas, the new version. Then export the contract.
- Add a test that sends the batch example from the documentation, and checks that it gives
200with one result per ticket.
Evidence for part 3: the contract test’s difference (the first lines are enough), and a screenshot of the new endpoint in /docs, opened.
Part 4: test it
Section titled “Part 4: test it”Uses Automated endpoint tests and Configuration and logging.
Write pytest tests for at least:
- The order of the results.
- The boundaries of the list: 0, 1, 20 and 21 tickets.
- One invalid ticket in the list, and the exact field in the error.
- A missing key, when a key is set.
- The classifier down (
classifier_mode="unavailable"). - Your size decision from Part 1.
Then break the route on purpose, for example reverse the results, and check that a test fails.
Evidence for part 4: the test functions, and the output of python -m pytest with every test passing.
Part 5: Postman
Section titled “Part 5: Postman”Uses First requests in Postman and Tests and repeatable runs.
- Add at least two requests to the collection. The first is a valid batch (tests: status, one result per ticket, the order). The second is an empty batch (tests:
422, the fieldtickets). - Export the collection into
postman/, and check that no file there contains a key. - Run the whole collection from the terminal against the local API, with the key from
--env-var.
Evidence for part 5: the summary table of the terminal run, and its exit code.
Part 6: deploy and verify
Section titled “Part 6: deploy and verify”Uses Hosting bridge, Publish safely and Verify and clean up.
- Create the app, set a new API key as a secret, and set
SHOW_DOCS, before you deploy. - Deploy. Check
/health,/ready, and a batch request without a key (401). - Run the collection with the Deployed environment.
- Set
CLASSIFIER_MODE=unavailable, and show that a batch request gives503with a request ID. Find that request in the logs. Then remove the setting. - Delete the app, unlink the folder, and remove the key from Postman.
- In a new virtual environment with only the dependencies from
pyproject.toml, start the API withfastapi run, a key andSHOW_DOCS=false. - Check
/health,/ready,/docs(404) and a batch request without a key (401). - Run the collection against it.
- Start it again with
CLASSIFIER_MODE=unavailable, and show that a batch request gives503with a request ID, and find the request in the log. - Write two sentences on what a real deployment would add that this simulation does not show.
Evidence for part 6: the outputs of each step (with the key removed), and for FastAPI Cloud, a line that the app is deleted.
Check your work
Section titled “Check your work”There is no reviewer for this course yet. Review your evidence with this table, or ask a colleague to use it. Mark each item as demonstrated, partially demonstrated or not yet demonstrated, with a reason. The course is complete when every item is demonstrated. You can improve an item and review it again as often as you need.
| Required evidence | Demonstrated when |
|---|---|
| Documented endpoint contract | The contract table covers every failure row. The OpenAPI document has the endpoint with a description, working examples and every error response. The reviewed contract file matches, and a test proves that the documented example works. The version change is explained. |
| Input and error validation | Every row of the contract table gives the planned status code and error shape. This includes the boundaries 0, 1, 20 and 21, and the exact field of an invalid ticket. Errors never contain internal details. |
| A Postman collection that runs from the command line | The collection is in the project, with tests for the batch endpoint. It runs from the terminal, and every test passes against the local API and the deployed (or simulated) API. It fails with exit code 1 when the API is down. |
| Repeatable local and deployed checks | pytest passes. The deployed or simulated API passes the collection. It shows a successful request, an invalid request and a controlled dependency failure (503 with a request ID). |
| Secrets outside source code | No key in the code, in postman/, in the README or in the evidence. The deployed key was new, stored as a secret, and is gone after the clean-up. |
A working happy path is not enough. Maybe a request without a key gets 200 while a key is set, or an error shows a traceback. Then the item is not yet demonstrated, even if everything else works.
Common mistake
20 tickets are allowed, but 20 tickets get 413
Symptom: a batch of 20 tickets with long bodies gets 413 body_too_large, although the contract says that up to 20 tickets are allowed.
Cause: two limits meet. Each ticket’s body may have 5,000 characters, and 20 of those are about 100 KB, but the whole request may have only 16 KB. Both limits are correct for one ticket. Together, they contradict each other for a batch.
Fix: decide, and make the contract say the truth. One option is to raise the body limit for the batch endpoint, and accept the larger memory use. The other is to keep 16 KB. Then document in the endpoint’s description that the whole batch must fit in 16 KB, with a test for it. Both are valid. An undocumented contradiction is not.
Recap
In this course, you went from one HTTP request to a deployed service that other programs can trust:
- HTTP: URLs, DNS, ports and TLS, methods, headers, bodies and status codes, and how to inspect them.
- The service: FastAPI routes, typed models, a separate classifier, and one error shape with stable codes.
- The contract: versioned routes, CORS for browsers, and OpenAPI documentation in Swagger UI, kept true by tests.
- Postman: collections, Postman environments, local-only secrets, tests, and runs from the command line.
- Reliability: pytest for every path, request IDs in logs, an API key, a body limit and a time limit.
- Deployment: production mode, secrets on the platform, liveness and readiness, smoke checks, logs and clean-up.
Later courses build on this API. They deploy a trained model behind it and put it in a container. They also run the Postman collection automatically on every release.