Top 30 API Design Interview Questions and Answers
30 multiple-choice questions on API Design, drawn from 30 bites out of the 48 tagged API Design on Tezvyn. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.
30 questions. Pick an answer, or open “Show the answer” to read it.
Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.
Question 1 of 30
When you annotate a FastAPI route parameter with a Pydantic model, what does the framework do with that type hint?
Show the answer
Answer: a · It leverages the hint for automatic request validation and OpenAPI schema generation
FastAPI reads type hints at startup to construct Pydantic models that validate incoming requests and generate OpenAPI schemas automatically. The distractor about runtime enforcement is wrong because Python itself ignores type hints during execution unless an external tool checks them.
Read the full bite: Explain Python type hints and their importance in FastAPI
Question 2 of 30
What single element most reduces churn when documenting a breaking API change for developers?
Show the answer
Answer: d · Concrete before-and-after migration steps for each breaking change
Developers churn when they cannot see how to fix their code; explicit before-and-after migration steps give a direct, actionable path. A celebratory tone or hiding the old behavior leaves users stranded and increases frustration.
Read the full bite: Structuring release notes for breaking API changes
Question 3 of 30
An endpoint declares a query parameter as q: Optional[str] with no default value. What happens when a client omits it?
Show the answer
Answer: c · FastAPI returns a 422 Unprocessable Entity error
FastAPI derives requirement from the presence or absence of a Python signature default, not from type hints, so Optional[str] without = None is still required and omitting it triggers a 422 error. Option D is a common misconception because Optional alone does not make a parameter optional in FastAPI.
Read the full bite: How does FastAPI distinguish required optional and default query parameters
Question 4 of 30
What combination of standard and code sources enables FastAPI's automatic interactive documentation?
Show the answer
Answer: d · It dynamically builds an OpenAPI schema from type hints, Pydantic models, decorators, and docstrings
FastAPI dynamically generates an OpenAPI schema by extracting metadata from type hints, Pydantic models, decorators, and docstrings, so no manual schema file is required. Option B is wrong because maintaining a separate openapi.yaml by hand is unnecessary and contradicts FastAPI's design.
Read the full bite: What standard and code elements power FastAPI's auto-generated API docs?
Question 5 of 30
What is the primary type-system benefit of declaring an interface as Producer<out T> when T only appears in return positions?
Show the answer
Answer: b · It lets Producer<String> be used where Producer<Any> is expected without caller-side wildcards.
Marking T with out makes Producer covariant, so Producer<String> is a subtype of Producer<Any> and callers never need wildcards. Option C is wrong because variance does not imply immutability; the class may still mutate state via operations that do not mention T.
Read the full bite: Explain Kotlin's declaration-site variance with in and out
Question 6 of 30
Which method correctly enables automatic JSON body validation in a FastAPI route?
Show the answer
Answer: a · Subclass BaseModel and declare it as the type of a path operation function parameter
FastAPI inspects path operation parameter type annotations to automatically parse and validate incoming JSON against a Pydantic BaseModel. Manually calling request.json() bypasses this automatic pipeline, and response_model only defines the outgoing response schema rather than request validation.
Read the full bite: How do you define a Pydantic model for FastAPI request body validation?
Question 7 of 30
You want a Rust function to read a string without taking ownership and accept both a String variable and a literal. Which parameter type achieves this?
Show the answer
Answer: b · &str
&str is a borrowed slice that coerces from &String and accepts literals directly, avoiding clones. &String is wrong because it rejects string literals, forcing callers to allocate a String they do not need.
Read the full bite: What type replaces String for read-only function parameters in Rust?
Question 8 of 30
When a FastAPI endpoint receives JSON with extra fields not defined in the Pydantic model, what occurs by default?
Show the answer
Answer: d · Pydantic silently drops the extra fields and the request succeeds
By default Pydantic ignores extra fields, silently dropping them so the model instantiates and the request succeeds. Option C is wrong because that strict 422 behavior only happens when you explicitly configure extra to forbid in model_config.
Read the full bite: How does Pydantic handle extra JSON fields, and how to configure it?
Question 9 of 30
You define a function return type as Product[] | { message: string }. What is the critical next step before using the returned value?
Show the answer
Answer: d · Use a type guard such as Array.isArray to narrow the union
Using a type guard like Array.isArray lets TypeScript narrow the union inside each branch, giving exact types and autocomplete. Simply returning the union without narrowing forces consumers to deal with both shapes manually, a subtler error that hides bugs until runtime.
Read the full bite: How do you type a function with two possible response shapes?
Question 10 of 30
Which is the strongest reason to prefer a string enum over a numeric enum for a status field returned by an external API?
Show the answer
Answer: a · String enums use human-readable runtime values that match the API wire format exactly, avoiding an extra mapping layer.
String enums let you assign API response values directly because their runtime values are the exact strings on the wire, unlike numeric enums which produce opaque integers and require a separate mapping. The most tempting distractor claims string enums offer reverse mapping, but that is actually a feature of numeric enums and is usually irrelevant for external API contracts.
Read the full bite: How would you use an enum to represent API statuses?
Question 11 of 30
Which TypeScript structure should you choose to make an ApiResponse<T> that cannot simultaneously hold both data and error properties?
Show the answer
Answer: d · A union of two interfaces sharing a status literal, one generic branch with data: T and the other with error: { code; message; }
A discriminated union with a shared literal status makes it impossible to represent both states at once and enables automatic type narrowing. Option A is a common mistake because optional fields and a broad string status allow objects where both data and error are present, absent, or mismatched.
Read the full bite: Write a generic ApiResponse<T> type with success and error states
Question 12 of 30
In the two-table versioning design, what is the main benefit of storing current_version_id in the articles table?
Show the answer
Answer: c · It lets the application fetch the latest article state without scanning the full version history
The correct answer is C because the pointer provides immediate access to the current snapshot, avoiding costly history scans. Distractor B is wrong since the design intentionally stores full snapshots rather than relying on diff reconstruction for lookups.
Read the full bite: Design a content versioning system with history and revert
Question 13 of 30
A FastAPI endpoint returns a UserDB model containing password_hash. Which strategy best prevents exposing the hash while keeping the API contract explicit and maintainable?
Show the answer
Answer: c · Create a separate UserOut model without password_hash and set response_model=UserOut on the endpoint.
A dedicated output model declaratively isolates the API contract from the database schema and prevents accidental leaks if new sensitive fields are added later. Option B is a tempting quick fix, but it keeps the sensitive field in the source model and hides the contract outside the type system, making it harder to maintain.
Read the full bite: How do you prevent password_hash from appearing in a FastAPI response?
Question 14 of 30
In a decoupled multi-channel architecture, how should article content be stored and delivered to consumers?
Show the answer
Answer: d · In structured, channel-agnostic fields exposed via an API with channel-specific rendering layers
Storing content in structured, channel-agnostic fields and delivering it through an API lets each channel render appropriately, while a shared HTML blob is tempting but wrong because forcing identical presentation breaks mobile layouts and email compatibility.
Question 15 of 30
What is the immediate output of a successfully executed Kotlin type-safe builder block?
Show the answer
Answer: a · A hierarchical tree of interconnected Kotlin objects representing the defined structure.
The card explicitly states that a builder block "doesn't generate a string" but rather "instantiate and link HTML, Head, and Title objects into a tree," with the "final result is a root HTML object." While builders are often used to eventually produce strings, their immediate output is an object hierarchy. Option C is a common misconception because builders are frequently used for markup generation.
Read the full bite: Kotlin's Type-Safe Builders: Code as Data
Question 16 of 30
Which approach is the idiomatic TypeScript solution for constructing a typesafe ApiRoute type that includes both /api/v1/<resource> collection paths and /api/v1/<resource>/{id} item paths from a finite Resource union?
Show the answer
Answer: b · A base route template interpolating Resource into /api/v1/, unioned with the same base route suffixed by /{id}
Template literal types automatically distribute a union through an interpolated position into every concrete string permutation, so unioning BaseRoute with BaseRoute/{id} is the idiomatic, machinery-free solution. Option A is tempting because it yields the same members, but it unnecessarily uses a mapped type when direct interpolation already expands the union, and C sacrifices compile-time exhaustiveness for false flexibility.
Read the full bite: Build a typesafe ApiRoute type using template literal types
Question 17 of 30
You move a helper package into an internal directory to restrict its use to your module. Which statement about the effects is true?
Show the answer
Answer: a · External modules are blocked from importing it by the compiler, while sibling packages in the same module can still import it freely
The Go compiler rejects imports of internal packages from outside the module, yet packages inside the same module may import them normally. Option B is tempting because unexported identifiers also limit visibility, but they only restrict access within a single package, not across packages in a module.
Read the full bite: What is the purpose of the internal directory in Go?
Question 18 of 30
What happens to extra fields on an object returned by a FastAPI endpoint when a response_model is declared?
Show the answer
Answer: b · FastAPI silently filters out fields not present in the response_model during serialization
The card explains that FastAPI automatically drops undeclared fields when serializing against the response_model. Option C represents the brittle manual approach the card explicitly warns against, whereas the response_model is designed to handle filtering for you.
Read the full bite: How would you use a Pydantic response_model to enforce output structure?
Question 19 of 30
In FastAPI, what primarily determines whether a function parameter is treated as a path parameter instead of a query parameter?
Show the answer
Answer: b · If the parameter name appears inside braces in the route path string
FastAPI inspects the route path template and treats parameters named in braces as path variables, while all others become query parameters. Although Path() can add metadata, it is not required for basic inference, and default values determine optionality rather than parameter location.
Read the full bite: Define a FastAPI endpoint with path and query parameters
Question 20 of 30
What architectural choice best prevents a feature-rich DataTable from becoming a monolith with dozens of props?
Show the answer
Answer: b · A headless logic core plus a column-definition config with per-column render functions
Separating headless state from rendering and driving structure with column configs and render functions lets features scale via config rather than prop accretion. Per-feature booleans and hardcoded rendering are exactly what causes the monolith.
Question 21 of 30
Which client-side strategy best maximizes throughput for a 100 req/min API without triggering excessive 429 errors?
Show the answer
Answer: b · Bound concurrency to a small worker pool, proactively pace requests using rate-limit headers, and apply exponential backoff with jitter on 429s.
The correct answer combines proactive throttling, header-aware dynamic pacing, bounded concurrency, and resilient retries as described in the card. Option A is tempting because it limits concurrency, but it still creates burst traffic and ignores headers, relying on the server to punish the client rather than preventing 429s proactively.
Read the full bite: Design a rate-limited REST API data collection script
Question 22 of 30
Which of the following correctly implements a global FastAPI handler for a custom ItemNotFoundError that returns a structured 404 JSON response?
Show the answer
Answer: a · Define an async handler with signature (request: Request, exc: ItemNotFoundError), register it with @app.exception_handler, and return a JSONResponse with status_code=404 and structured content.
The correct approach registers a global handler with the Starlette-injected request parameter and returns a proper JSONResponse, centralizing error handling across all routes. Option C is tempting because it uses the correct response type, but scattering try/except blocks in every route defeats the purpose of centralized exception handling and creates unnecessary duplication.
Read the full bite: Implement a custom exception handler to catch ItemNotFoundError and return 404
Question 23 of 30
In an SEO content gap pipeline, which operation and key set correctly isolates competitor keywords your domain does not rank for?
Show the answer
Answer: b · Left anti-join on keyword, geography, and device, filtering for competitor rank in the top 20 and your domain absent or below position 100
A left anti-join on keyword, geography, and device with rank filters correctly finds competitor keywords you do not own. Option C is tempting because it compares rankings, but an inner join on keyword text alone ignores geo and device while returning shared terms rather than true gaps.
Read the full bite: Design a content gap tool: data sources and core logic
Question 24 of 30
You need a FastAPI dependency that combines a path parameter and a request header. What is the correct implementation pattern?
Show the answer
Answer: d · Annotate each parameter in the dependency function with its source (e.g., Path, Header) and declare the function as a dependency with Depends().
FastAPI inspects dependency signatures using the same resolution engine as endpoints, so annotating parameters with Path, Header, or similar and using Depends() lets the framework inject them automatically. Option B is tempting for developers familiar with lower-level frameworks, but manually parsing Request bypasses validation and defeats the purpose of FastAPI's dependency injection system.
Read the full bite: How would you implement a dependency requiring multi-source parameters?
Question 25 of 30
What is the strongest way to guarantee every icon-only Button has an accessible name?
Show the answer
Answer: d · Use a TypeScript discriminated union so the icon-only variant makes aria-label a required prop
Making the label required at the type level turns omission into a compile error, the strongest guarantee. Documentation is ignorable, filenames are meaningless to users, and tooltip-only labels are not reliably announced by screen readers.
Read the full bite: Enforcing an accessible name on icon-only buttons
Question 26 of 30
An API returns 200 OK for every successful response, including resource creation. What semantic information is being lost?
Show the answer
Answer: a · That a new resource was created, which 201 (with a Location header) signals
201 Created communicates that a new resource now exists and where to find it via Location; a generic 200 hides that distinction. Auth, caching, and content type are conveyed by other mechanisms.
Read the full bite: Status codes for successful POST and GET
Question 27 of 30
When an API returns HTTP 200 for both success and failure, which strategy best enforces type safety across the network boundary?
Show the answer
Answer: b · Treat the body as unknown, use a type guard to validate it against a discriminated union, and wrap the outcome in a Result type
Treating the body as unknown and validating it with a type guard forces runtime checks and enables narrowing to a discriminated union, which a Result type then surfaces to callers. Casting with as is dangerous because it bypasses both runtime validation and the type checker, allowing error payloads to be treated as success data.
Read the full bite: How do you handle an API returning 200 for success and failure?
Question 28 of 30
A mobile client retries a request after a network timeout. Which request can it safely retry without risking duplicate resources?
Show the answer
Answer: b · PUT /users/42 with the full updated representation
PUT to a known URL is idempotent, so a retry converges to the same state. POST is not idempotent, so retrying it can create duplicate users or orders.
Question 29 of 30
In an Express 4 API with a central error middleware, async route errors still hang the request while sync throws work fine. What is missing?
Show the answer
Answer: b · An asyncHandler wrapper that catches promise rejections and calls next
Express 4 auto-catches synchronous throws but not promise rejections, so async handlers need a wrapper that forwards rejections to next. Moving the error handler before routes would actually break it.
Read the full bite: Centralized error handling in an Express API
Question 30 of 30
What is the strongest argument against adding a variant only one team needs directly into the core library?
Show the answer
Answer: a · It permanently enlarges the API surface the core team must maintain for low reuse
A single-team variant adds lasting maintenance and API-surface cost for little reuse, the core bloat concern. Adding a variant is typically a minor bump, not major, and accessibility and optional variants are both perfectly achievable.
Read the full bite: Deciding whether a one-off variant belongs in core
Could you explain these out loud?
That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.