Q261: Secure API Design for Frontend Applications
What Interviewers Want To Evaluate
Interviewers want to know whether you can design frontend-facing APIs that are safe, predictable, observable, and pleasant to consume.
They are checking whether you understand that frontend security is not only about hiding buttons.
They want to hear about authorization, validation, rate limits, idempotency, pagination, errors, privacy, caching, and mutation behavior.
Short Interview Answer
Secure API design for frontend applications starts with server-side authorization, explicit request and response contracts, runtime validation, safe mutation semantics, clear errors, privacy-aware payloads, and observability. The UI can guide users, but the API must enforce permissions and ownership. I would design reads and writes separately, avoid overfetching sensitive fields, use idempotency for risky mutations, validate all external input, rate-limit abuse paths, and expose errors that help the UI recover without leaking internals.
Detailed Interview Answer
Frontend applications live on API contracts.
A weak API contract creates frontend bugs even when the React code is clean.
A secure API answers:
who is calling?
what are they allowed to do?
what input shape is valid?
what data may be returned?
what side effect will happen?
how is failure represented?
how is abuse limited?
how is the action audited?
These questions belong to the API boundary, not only the component tree.
Authorization Is Server-Side
The browser is not the authority.
Frontend checks are useful for UX.
They can hide unavailable actions.
They can prevent obvious invalid submissions.
They can show helpful upgrade prompts.
But protected data and mutations must be checked server-side.
Do not rely on:
hidden buttons
disabled controls
route guards only
client-side role checks
localStorage permissions
Those are hints, not security boundaries.
Object Ownership
Many API bugs are ownership bugs.
Example:
GET /api/reports/123
The server must verify that the current user can read report 123.
It is not enough that the user is authenticated.
Ask:
does this user own the object?
does their organization own it?
does their role permit this action?
is the object in the correct lifecycle state?
This prevents insecure direct object reference style problems.
Input Validation
TypeScript does not validate network input.
Every API should validate runtime data.
Validation should check:
required fields
field types
length limits
allowed enum values
numeric ranges
cross-field rules
authorization-dependent rules
Return validation errors in a UI-friendly shape.
Example:
field: "email"
code: "invalid_format"
message: "Enter a valid email address."
Response Shape
Do not return data just because the database has it.
Frontend-facing responses should be intentionally shaped.
Avoid leaking:
internal IDs when unnecessary
private notes
permission metadata
debug traces
feature flag internals
other users' data
raw provider responses
Give the UI the data it needs, not the whole table.
Mutation Design
Mutations should be explicit.
Use clear endpoints or server actions for:
create
update
delete
archive
publish
restore
invite
export
Risky mutations need:
authorization
validation
CSRF protection where relevant
idempotency
audit logs
rate limits
clear success and failure states
Idempotency is especially useful for payments, exports, retries, and background jobs.
Error Contracts
Frontend teams need reliable errors.
Avoid returning unstructured strings for everything.
Useful error dimensions:
status code
machine code
human message
field errors
retryable flag
request ID
support reference
A 401 should not be handled like a 422.
A 409 conflict should not look like a generic 500.
Rate Limiting and Abuse
Frontend-facing APIs are exposed to the internet.
Protect endpoints such as:
login
password reset
search
export
AI generation
file upload
invite
checkout
Rate limiting should be paired with clear UI behavior.
The user should know whether to retry later, reduce input, or contact support.
Caching and Privacy
Cache public reads differently from private reads.
Ask:
is this response public?
is it user-specific?
does it vary by auth, locale, or experiment?
can a shared cache store it?
how is it invalidated?
Bad API caching can leak data or show stale permissions.
Observability
Every important API should be debuggable.
Capture:
request ID
route
method
status
latency
user or tenant context
error code
release version
rate-limit events
Do not log secrets or sensitive payloads.
Good observability lets frontend and backend teams debug from the same evidence.
Interview Example
If asked, "How would you design a save-progress API for this learning app?"
Say:
authenticate the user if progress is cloud-backed
validate question ID and completion state
verify the question exists
prevent users from writing another user's progress
make repeated saves idempotent
return a typed success shape
rate-limit noisy clients
avoid logging answer text unless necessary
support offline retry if product needs it
That is stronger than only saying "POST progress to the server."
Common Mistakes
Common mistakes include:
trusting client roles
returning full database records
missing object ownership checks
using generic errors for every failure
not validating runtime input
not making retries safe
leaking secrets in logs
forgetting rate limits on expensive endpoints
Final Mental Model
A secure API is a product boundary.
Frontend code can make the experience kind and clear.
The API must enforce who can do what, with which data, under which conditions, and with enough evidence to debug failures.