Design a Small API with Clear Contracts and Useful Errors
An original worked API guide: define task endpoints, validate permissions and errors, and handle retries without accidental duplicate records.
An original worked API guide: define task endpoints, validate permissions and errors, and handle retries without accidental duplicate records.
Help me design a small JSON API for a fictional personal task tracker. A signed-in user can create a task, list their own tasks, and mark one complete. Each task has a title of 1 to 120 characters after trimming and a done flag that starts as false.
Describe the endpoints, accepted fields, and successful responses before writing implementation code. Include an example request and response for creating 'Review onboarding copy'. Treat the current session as the source of ownership rather than accepting an owner from the request.
A small contract is POST /tasks to create a task from a title, GET /tasks to list the caller's tasks, and PATCH /tasks/{id} to set the done flag. For this exercise, creation accepts only a string title; the update accepts only a boolean done value. The server supplies the ID, owner, and timestamps. Define whether unknown fields are rejected; rejecting them makes accidental client assumptions visible.
The sample creation body is . A successful example response is , with status 201 and a Location header pointing to the newly created resource. The example identifier is illustrative rather than a requirement for the database's ID format. Never echo an owner supplied by the client as an authoritative identity.
{"title":"Review onboarding copy"}{"id":"task_example_123","title":"Review onboarding copy","done":false}List returns only tasks owned by the authenticated user, with an explicitly documented order such as newest first and a bounded page size. Completion returns the updated representation with status 200. These status choices follow the general success meanings documented in MDN's HTTP status reference; the resource shapes and field restrictions are our proposed application contract.
Extend the API contract to cover malformed JSON, a title made entirely of spaces, an unauthenticated request, and an attempt to complete another user's task. Choose a consistent error shape that a client can display without parsing free-form server messages.
Show how to order authentication, validation, and ownership checks in the handler. Explain what the client can safely display and what diagnostic information belongs in server logs. Avoid returning database internals or stack traces to the browser.
Use a stable error envelope such as {"error":{"code":"INVALID_TITLE","message":"Enter a title from 1 to 120 characters.","field":"title"}}. This guide chooses 400 for malformed JSON and 422 for a well-formed payload that violates a field rule. Choose 401 when the request lacks valid authentication. For a missing or inaccessible task, use the same 404 response so this API does not reveal whether another user's task exists.
A practical handler sequence is to establish the session, parse the body within a size limit, validate its shape, and perform a database operation scoped to both task ID and session owner ID. For completion, UPDATE ... WHERE id = supplied_id AND owner_id = session_owner RETURNING ... can enforce the ownership condition in the operation itself. A missing returned row maps to the documented unavailable-task response.
The browser can display the stable message and associate the field identifier with the relevant control. Unexpected failures should receive a generic server error and a request reference that can be matched to protected logs. Record enough context to investigate the failure without logging credentials or unnecessary request content. The exact status selection is part of the published contract; clients should rely on the error code for the specific recovery action.
Consider a task-creation request that succeeds in the database but times out before the browser receives the response. Design an application-level retry policy so pressing Retry does not necessarily create a second task. Explain the difference between retrying creation and setting done to true again.
Give me a compact contract-test plan that covers success, validation, ownership, and retry behavior. Include what happens if a client reuses the same creation key with a different title. Keep the plan independent of a particular web framework.
One design is to accept a client-generated request key for creation, scope it to the authenticated user, and store the key, a normalized payload fingerprint, and the resulting task in one transaction. Enforce uniqueness on the owner-and-key pair so concurrent retries cannot both create a task. A replay with the same key and payload returns the recorded result; define the storage lifetime so clients know how long this guarantee lasts.
If the same key arrives with a different title, reject it with a documented conflict response rather than returning an unrelated task. Setting done to true repeatedly can leave the resource in the same state, but completion-triggered side effects need their own duplicate prevention. For example, a notification should be emitted only for the actual false-to-true transition, with reliable delivery handled separately if the application requires it.
Contract checks should create a valid task, reject whitespace-only and oversized titles, reject an invalid done value, deny another account's update, and confirm bounded list results. Add two concurrent creations with the same key, a replay after a simulated lost response, and a mismatched-payload replay. These are proposed assertions: one task for the same approved creation request, a conflict for key misuse, and no unauthorized modification.
Comments 0
Share how you would use this prompt or suggest a useful improvement.