Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 15.00: Scoping the service and its contract

The capstone begins with the contract, including the errors and the guarantees.

Request, response, errors, guarantees, scope, budget

A complete service scope with four checks against it.

The code prints it and runs them.

import json

scope = {
    "service": "ticket classification API for internal tools",
    "endpoint": "POST /v1/classify",
    "request": {"text": "str, 1-4000 chars"},
    "response": {"category": "billing|technical|account|other",
                 "confidence": "float 0-1", "meta": "request_id, versions, cost"},
    "errors": {"401": "invalid API key", "413": "input too long",
               "422": "validation failed", "429": "rate limited",
               "503": "model unavailable"},
    "guarantees": ["no request body is logged",
                   "category is always one of the four",
                   "no call is made if the daily budget is exhausted"],
    "not_in_scope": ["storing tickets", "user accounts", "a browser client"],
    "budget": {"daily_usd": 50.0, "p95_latency_ms": 2000},
}
print(json.dumps(scope, indent=2))

checks = [("errors are enumerated", len(scope["errors"]) >= 4),
          ("guarantees are testable", len(scope["guarantees"]) == 3),
          ("out of scope is stated", len(scope["not_in_scope"]) > 0),
          ("budget is bounded", scope["budget"]["daily_usd"] > 0)]
for check, ok in checks:
    print(f"  {'OK  ' if ok else 'FAIL'} {check}")

The guarantees list is what constrains the implementation permanently: no body logged, category always from the allowed set, no call once the budget is exhausted. Each becomes a test in the third unit of this module.

not_in_scope is the field that prevents drift. Storing tickets and user accounts are both reasonable next requests and both change the service into something else.

The mistake this prevents

The mistake is scoping by what the model can do. Scope by the contract you are prepared to keep - the guarantees are promises, and every one of them constrains what you may build later.

Takeaway

Write the contract first: request, response, every error, and the guarantees. Each guarantee becomes a test and each constrains the implementation.