Skip to content

API Design for Complex Workflows

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.

  • Correct (RESTful): GET /resources
    • Logic: “Go to the resources drawer (/resources) and GET (GET) its contents.”
  • Incorrect (RPC-style): GET /getAllResources
    • Logic (Confusing): “Perform a GET (GET) action on an endpoint named ‘getAllResources’.” This is redundant.
  • 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).
  • Incorrect (RPC-style): POST /createNewResource

This principle is powerful for handling relationships:

  • Correct (RESTful): GET /resources/12345/orders
    • Logic: “Inside the resources drawer, find the file for resource 12345, then open its sub-drawer named orders, and GET all the contents.” This hierarchy is intuitive.

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.

  • 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 PREREGISTERED status, with validation requiring only the reference_number field.
  • 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 ACTIVE status, validating all required fields.

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.

  • 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"
    }
  • 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"
    }

  1. Clarity & Predictability: The API becomes self-documenting and consistent. Once you understand the pattern for /resources, you can predict how /orders will work.
  2. Safety & Security: It prevents accidental modification of the wrong data. The contact-info endpoint cannot interfere with the resource’s classification.
  3. Precise Validation: Each endpoint has its own DTO, allowing for validation rules tailored specifically to that action.
  4. Decoupled Logic: Your backend service code becomes cleaner. The updateContactInfo function has a single responsibility, making it easier to test and maintain.