Skip to content

Instantly share code, notes, and snippets.

@abdelghanyMh
Created February 26, 2025 20:58
Show Gist options
  • Save abdelghanyMh/c61a5fa3fb79f3cd06da927183e2ef1e to your computer and use it in GitHub Desktop.
Save abdelghanyMh/c61a5fa3fb79f3cd06da927183e2ef1e to your computer and use it in GitHub Desktop.

Resources and Sub-Resources

Let’s clarify the distinction between POST and PUT in the context of resources and sub-resources, using the Cash Card and Invoice APIs as examples:


Key Idea: Resources vs. Sub-Resources

  • A resource is any entity your API manages (e.g., a Cash Card or Invoice).
  • A sub-resource is a child entity nested under a parent resource (e.g., a specific Cash Card under the /cashcards collection).

POST Creates Sub-Resources

  • How it works:

    • The client sends a request to a parent URI (e.g., POST /cashcards).
    • The server generates a unique ID (e.g., 101) and creates a new sub-resource under the parent URI.
    • The new resource’s URI is determined by the server (e.g., /cashcards/101).
  • Example: Cash Card API

    • Client sends:
      POST /cashcards
      { "amount": 50 }
    • Server responds with:
      201 Created
      Location: /cashcards/101
    • The new Cash Card is a sub-resource of /cashcards.
  • Why POST?
    The client doesn’t know the final URI upfront—it depends on the server-generated ID. POST is designed for creating sub-resources in a collection.


PUT Creates or Replaces Resources at a Specific URI

  • How it works:

    • The client sends a request to a specific URI (e.g., PUT /invoices/1234-567).
    • The server creates or replaces the resource exactly at that URI.
    • No new sub-resource is created—the URI is fully specified by the client.
  • Example: Invoice API

    • Client sends:
      PUT /invoices/1234-567
      { "total": 100 }
    • Server responds with:
      201 Created (or 200 OK if updating)
      Location: /invoices/1234-567
    • The Invoice exists at the exact URI provided by the client.
  • Why PUT?
    The client knows the full URI in advance (e.g., using a natural key like an invoice number). PUT is idempotent, meaning repeated requests have the same result (safe for client-controlled URIs).


Visual Comparison

Action POST PUT
Target URI Parent collection (e.g., /cashcards) Specific resource (e.g., /invoices/1234-567)
Who defines the URI? Server Client
Result Creates a sub-resource (e.g., /cashcards/101) Creates/replaces resource at the client-specified URI
Idempotent? No (multiple POSTs create duplicates) Yes (multiple PUTs have the same effect)

Why This Matters

  1. POST is like adding a new file to a folder:

    • You ask the server, "Add this to the cashcards folder."
    • The server names the file (e.g., 101.json).
  2. PUT is like saving a file to an exact path:

    • You tell the server, "Save this as invoices/1234-567.json."
    • You control the filename and location.

Summary

  • Use POST when:

    • The server generates the resource’s ID/URI (sub-resource creation).
    • You’re working within a collection (e.g., /cashcards).
  • Use PUT when:

    • The client specifies the full URI (natural key).
    • You want idempotent behavior (no duplicates on retries).

This distinction ensures your API follows RESTful principles and behaves predictably.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment