API Design for Complex Workflows
Action-Specific Endpoints
Section titled “Action-Specific Endpoints”The core principle is to design APIs that reflect the user’s actions and processes, rather than being strictly tied to the database schema. An action might involve updating multiple tables, changing a record’s status, or triggering notifications. Creating a dedicated endpoint for each specific action leads to a cleaner, safer, and more maintainable backend.
The “Nouns over Verbs” Principle: Why We Use Plural Nouns for Resources
Section titled “The “Nouns over Verbs” Principle: Why We Use Plural Nouns for Resources”A foundational concept in REST API design is to treat your API like a large digital filing cabinet.
- The URI (e.g.,
/resources) is the label on a drawer, indicating the type of resource inside. - The HTTP Method (e.g.,
GET,POST) is the action you want to perform on the contents of that drawer.
Therefore, the drawer’s label should be a noun that describes what is inside (e.g., “resources”, “orders”), not a verb describing an action (e.g., “getResources”, “createOrder”). Using plural nouns (resources instead of resource) is the established convention to signify that the URI represents a collection of that resource.
Practical Comparison
Section titled “Practical Comparison”Getting all resources:
Section titled “Getting all resources:”- Correct (RESTful):
GET /resources- Logic: “Go to the resources drawer (
/resources) and GET (GET) its contents.”
- Logic: “Go to the resources drawer (
- Incorrect (RPC-style):
GET /getAllResources- Logic (Confusing): “Perform a GET (
GET) action on an endpoint named ‘getAllResources’.” This is redundant.
- Logic (Confusing): “Perform a GET (
Creating a new resource:
Section titled “Creating a new resource:”- Correct (RESTful):
POST /resources- Logic: “Go to the resources drawer (
/resources) and add (POST) a new file.” (The new resource’s data is in the request body).
- Logic: “Go to the resources drawer (
- Incorrect (RPC-style):
POST /createNewResource
This principle is powerful for handling relationships:
- Correct (RESTful):
GET /resources/12345/orders- Logic: “Inside the
resourcesdrawer, find the file for resource12345, then open its sub-drawer namedorders, andGETall the contents.” This hierarchy is intuitive.
- Logic: “Inside the
Example 1: Resource Registration Scenarios
Section titled “Example 1: Resource Registration Scenarios”This demonstrates how to handle pre-register and full-register cases, which are specific actions on the /resources collection.
Case A: Pre-register
Section titled “Case A: Pre-register”- Workflow: A staff member needs to reserve a reference number in advance, without having the full entity details.
- API Endpoint:
POST /resources/preregister - Request Body (DTO):
{"reference_number": "REF-00001"}
- Behind the Scenes: The system creates a resource record with a
PREREGISTEREDstatus, with validation requiring only thereference_numberfield.
Case B: Full Registration
Section titled “Case B: Full Registration”- Workflow: A user creates a complete new entity profile with all required information.
- API Endpoint:
POST /resources/register - Request Body (DTO):
{"reference_number": "REF-00002","first_name": "John","last_name": "Doe","date_of_birth": "1985-10-20","address": "123 Main Street, Springfield","phone_number": "081-234-5678"}
- Behind the Scenes: The system creates a complete resource record with an
ACTIVEstatus, validating all required fields.
Example 2: Section-based Updates
Section titled “Example 2: Section-based Updates”The UI will have many sections for editing information. This is where action-specific endpoints on a particular resource are most effective.
Important Note on PUT vs. PATCH: For updating partial data, PATCH is the correct HTTP method. PATCH is for partial updates, while PUT is for replacing an entire resource.
Case A: Updating General Information
Section titled “Case A: Updating General Information”- Workflow: Staff updates a resource’s display name or key attributes.
- API Endpoint:
PATCH /resources/{resourceId}/general-info - Request Body (DTO):
{"first_name": "Johnathan","last_name": "Doe","date_of_birth": "1985-10-21"}
Case B: Updating Contact Information
Section titled “Case B: Updating Contact Information”- Workflow: The entity informs staff of a new address or phone number.
- API Endpoint:
PATCH /resources/{resourceId}/contact-info - Request Body (DTO):
{"address": "456 New Avenue, Springfield","emergency_contact": {"name": "Jane Doe","phone_number": "089-876-5432"}}
Case C: Updating Category / Classification
Section titled “Case C: Updating Category / Classification”- Workflow: An administrator reclassifies a resource’s category or tier.
- API Endpoint:
PATCH /resources/{resourceId}/classification - Request Body (DTO):
{"category": "premium","tier": "enterprise"}
Summary of Benefits for Complex Systems
Section titled “Summary of Benefits for Complex Systems”- Clarity & Predictability: The API becomes self-documenting and consistent. Once you understand the pattern for
/resources, you can predict how/orderswill work. - Safety & Security: It prevents accidental modification of the wrong data. The
contact-infoendpoint cannot interfere with the resource’sclassification. - Precise Validation: Each endpoint has its own DTO, allowing for validation rules tailored specifically to that action.
- Decoupled Logic: Your backend service code becomes cleaner. The
updateContactInfofunction has a single responsibility, making it easier to test and maintain.