KAHIBARO
Discord Login Register

7.9 PATCH Requests

Understanding PATCH Requests

PATCH is an HTTP method used to make partial updates to a resource. Where PUT usually replaces a whole resource, PATCH is used when you only want to change specific fields.

In backend development, this is very common for user profile updates, settings pages, or any situation where the client edits only part of an object.

Key idea:
Use PATCH when updating only some fields of a resource, not the entire representation.

To keep this chapter focused, we will only talk about what is specific to PATCH compared to other HTTP methods like GET or POST, and how to design and handle PATCH endpoints in REST APIs.


When to Use PATCH

Partial vs Full Updates

The most important distinction is between PUT and PATCH.

Example resource, a user profile in JSON:

json
{
  "id": 123,
  "email": "user@example.com",
  "full_name": "Alice Smith",
  "bio": "Backend developer",
  "is_active": true
}

Example: Using PUT vs PATCH

Using PUT to change the bio might look like:

http
PUT /users/123
Content-Type: application/json
{
  "id": 123,
  "email": "user@example.com",
  "full_name": "Alice Smith",
  "bio": "New bio",
  "is_active": true
}

The client must send all fields, not just the changed one.

Using PATCH to change only the bio:

http
PATCH /users/123
Content-Type: application/json
{
  "bio": "New bio"
}

The server updates only the bio field and keeps other fields as they are.

Rule:
If you are replacing a resource, use PUT.
If you are modifying part of a resource, use PATCH.


Designing PATCH Endpoints

Typical PATCH URL Design

PATCH endpoints usually follow the same URL pattern as other operations on a single resource, for example:

OperationHTTP MethodExample URL
Get a userGET/users/123
Replace a userPUT/users/123
Partially update a userPATCH/users/123
Delete a userDELETE/users/123

You do not create a separate URL just because you use PATCH. The method changes, not the path.

What Should the PATCH Body Look Like?

There are two common strategies:

  1. Partial resource representation (most common and simple)
  2. Patch document formats like JSON Patch or JSON Merge Patch
1. Simple Partial Representation

In many REST APIs, a PATCH request body is simply a subset of the resource fields. Every field that appears is updated, others are left alone.

Example: Update a user’s full_name and is_active:

http
PATCH /users/123
Content-Type: application/json
{
  "full_name": "Alice B. Smith",
  "is_active": false
}

Server behavior:

This is straightforward, readable, and works well in many APIs.

2. JSON Patch and JSON Merge Patch (Overview)

These are more advanced, standardized formats. You do not need to fully implement them when starting, but you should know they exist:

FormatContent-TypeIdea
JSON Patchapplication/json-patch+jsonA list of operations (add, remove, replace)
JSON Merge Patchapplication/merge-patch+jsonPartial document that is merged

Example JSON Patch to change bio:

http
PATCH /users/123
Content-Type: application/json-patch+json
[
  { "op": "replace", "path": "/bio", "value": "Updated bio" }
]

In beginner-level projects, the simple partial representation approach is usually enough.


Typical Use Cases for PATCH

Updating User Profiles

Common PATCH endpoint:

http
PATCH /users/me
Content-Type: application/json
{
  "full_name": "New Name",
  "bio": "New bio"
}

Updating Resource Status or Flags

Often you only modify one or two flags, such as is_active, status, or is_published.

Example, deactivate a post:

http
PATCH /posts/42
Content-Type: application/json
{
  "is_published": false
}

Example, change an order status:

http
PATCH /orders/1001
Content-Type: application/json
{
  "status": "shipped"
}

Incremental Changes to Settings

You may want to update app settings where not all values are known at once.

http
PATCH /settings/notifications
Content-Type: application/json
{
  "email_notifications": true
}

Other notification settings stay the same because they are not included.


Behavior and Semantics of PATCH

Idempotency

Idempotency means:

Performing the same operation multiple times has the same effect as performing it once.

Example of a non-idempotent PATCH:

http
PATCH /accounts/10
Content-Type: application/json
{
  "increment_balance": 100
}

If the server interprets this as "add 100 to balance", then sending the same request twice adds 200. That is not idempotent.

Example of an idempotent PATCH:

http
PATCH /accounts/10
Content-Type: application/json
{
  "balance": 500
}

If this sets balance to 500, then sending this request multiple times leaves the final balance at 500.

Recommendation:
Try to design PATCH operations as idempotent when possible.
Update specific field values, not "add", "toggle", or "increment" actions.

How to Handle Missing Fields

You must decide:

For partial updates, the usual behavior is:

Example:

Current user:

json
{
  "id": 1,
  "full_name": "Alice",
  "bio": "Hello",
  "is_active": true
}

PATCH request:

http
PATCH /users/1
Content-Type: application/json
{
  "bio": null
}

Result (assuming bio can be null):

json
{
  "id": 1,
  "full_name": "Alice",
  "bio": null,
  "is_active": true
}

Handling Unknown or Forbidden Fields

If the client sends a field that does not exist or is not allowed to be modified, you must decide what to do:

Example of an invalid PATCH body:

http
PATCH /users/1
Content-Type: application/json
{
  "id": 99,
  "created_at": "2020-01-01T00:00:00Z"
}

You probably do not want the client to modify id or created_at. A common approach is:

Validation and Error Handling with PATCH

Validating Partial Inputs

With PATCH, some fields may be missing. Your backend must:

  1. Accept that some fields are not present at all.
  2. Validate only the fields that are present.
  3. Combine them with existing resource values when needed.

Example rules for /users/{id}:

PATCH request:

http
PATCH /users/1
Content-Type: application/json
{
  "full_name": "",
  "email": "not-an-email"
}

Response:

http
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
  "detail": [
    { "field": "full_name", "message": "Must not be empty." },
    { "field": "email", "message": "Invalid email address." }
  ]
}

Only the fields provided are validated.

Common Status Codes for PATCH

Status CodeWhen to Use for PATCH
200 OKSuccessful update, returns the updated resource
204 No ContentSuccessful update, returns no body
400 Bad RequestInvalid data, unknown fields, validation errors
401 UnauthorizedCaller not authenticated
403 ForbiddenCaller authenticated but not allowed to modify resource
404 Not FoundResource does not exist
409 ConflictUpdate conflicts with existing state (e.g. unique email)

Example success response with updated resource:

http
HTTP/1.1 200 OK
Content-Type: application/json
{
  "id": 1,
  "email": "user@example.com",
  "full_name": "New Name",
  "bio": "New bio",
  "is_active": true
}

Example success response with no content:

http
HTTP/1.1 204 No Content

Examples of PATCH in a REST API

Example 1: Update a Todo Item

Imagine a todo resource:

json
{
  "id": 10,
  "title": "Buy groceries",
  "description": "Milk, eggs, bread",
  "completed": false,
  "priority": "medium"
}
Change only the `completed` field
http
PATCH /todos/10
Content-Type: application/json
{
  "completed": true
}

Result:

json
{
  "id": 10,
  "title": "Buy groceries",
  "description": "Milk, eggs, bread",
  "completed": true,
  "priority": "medium"
}
Change `title` and `priority` together
http
PATCH /todos/10
Content-Type: application/json
{
  "title": "Buy groceries and snacks",
  "priority": "high"
}

Example 2: Partially Updating an Order

Order resource:

json
{
  "id": 1001,
  "status": "pending",
  "shipping_address": "123 Main St",
  "billing_address": "123 Main St",
  "items": [
    { "product_id": 5, "quantity": 2 },
    { "product_id": 8, "quantity": 1 }
  ]
}
Change only status
http
PATCH /orders/1001
Content-Type: application/json
{
  "status": "shipped"
}
Change shipping address and status
http
PATCH /orders/1001
Content-Type: application/json
{
  "status": "processing",
  "shipping_address": "456 New Address"
}

You do not need to send items or other fields.

Example 3: Clearing a Field

Suppose a user has an optional bio that can be removed.

Current:

json
{
  "id": 1,
  "full_name": "Alice",
  "bio": "Hello",
  "is_active": true
}

Client wants to delete the bio text:

http
PATCH /users/1
Content-Type: application/json
{
  "bio": null
}

If your API allows bio = null, this is a clear way to say "remove the bio". You must document this behavior so clients know how to clear fields.


Practical Design Tips for PATCH

Keep the Model Simple

For beginners, use this approach:

  1. Accept a JSON object with any subset of resource fields.
  2. For each field:
    • If present, validate and update the field.
    • If absent, leave the field unchanged.
  3. Return 200 OK with the updated resource.

Example for a blog post resource:

json
{
  "id": 5,
  "title": "Original title",
  "content": "Original content",
  "tags": ["python"],
  "is_published": false
}

PATCH request:

http
PATCH /posts/5
Content-Type: application/json
{
  "title": "Updated title",
  "tags": ["python", "backend"]
}

Updated resource:

json
{
  "id": 5,
  "title": "Updated title",
  "content": "Original content",
  "tags": ["python", "backend"],
  "is_published": false
}

Avoid Mixing Behavior and Data

Try not to overload PATCH with procedural commands like:

json
{
  "action": "publish"
}

It is usually clearer to update the state directly:

json
{
  "is_published": true
}

Using state fields makes your API easier to reason about.

Document How PATCH Works in Your API

Your API documentation should explain:

This helps clients avoid surprises when using partial updates.


Summary

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!