7.9 PATCH Requests
Table of Contents
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.
- PUT: The client sends the entire resource representation.
If some fields are omitted, the server often treats them as default or null, or rejects the request. - PATCH: The client sends only the fields that need to be changed.
Fields that are not sent remain unchanged.
Example resource, a user profile in 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:
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:
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:
| Operation | HTTP Method | Example URL |
|---|---|---|
| Get a user | GET | /users/123 |
| Replace a user | PUT | /users/123 |
| Partially update a user | PATCH | /users/123 |
| Delete a user | DELETE | /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:
- Partial resource representation (most common and simple)
- 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:
PATCH /users/123
Content-Type: application/json
{
"full_name": "Alice B. Smith",
"is_active": false
}Server behavior:
- Change
full_nameto"Alice B. Smith" - Change
is_activetofalse - Leave
emailandbiounchanged
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:
| Format | Content-Type | Idea |
|---|---|---|
| JSON Patch | application/json-patch+json | A list of operations (add, remove, replace) |
| JSON Merge Patch | application/merge-patch+json | Partial document that is merged |
Example JSON Patch to change bio:
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:
PATCH /users/me
Content-Type: application/json
{
"full_name": "New Name",
"bio": "New bio"
}- The user might leave out fields like
emailthat they do not want to change. - The server updates only the provided fields.
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:
PATCH /posts/42
Content-Type: application/json
{
"is_published": false
}Example, change an order status:
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.
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.
GETis idempotent.PUTis supposed to be idempotent.- PATCH is not guaranteed to be idempotent, but you can design it to be.
Example of a non-idempotent PATCH:
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:
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:
- If a field is not present in the PATCH body, do you:
- leave it unchanged, or
- set it to null or a default?
For partial updates, the usual behavior is:
- If a field is omitted, leave it unchanged.
- If a field is included with null, set it to
nullif allowed.
Example:
Current user:
{
"id": 1,
"full_name": "Alice",
"bio": "Hello",
"is_active": true
}PATCH request:
PATCH /users/1
Content-Type: application/json
{
"bio": null
}
Result (assuming bio can be null):
{
"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:
- Ignore unknown fields, or
- Return a client error, for example
400 Bad Request.
Example of an invalid PATCH body:
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:
- Reject the request with
400 Bad Request - Explain that these fields cannot be modified
Validation and Error Handling with PATCH
Validating Partial Inputs
With PATCH, some fields may be missing. Your backend must:
- Accept that some fields are not present at all.
- Validate only the fields that are present.
- Combine them with existing resource values when needed.
Example rules for /users/{id}:
full_name: string length 1 to 100bio: string length 0 to 500 or nullemail: must be valid format and unique
PATCH request:
PATCH /users/1
Content-Type: application/json
{
"full_name": "",
"email": "not-an-email"
}full_namefails length validation (0 characters)emailfails email format validation
Response:
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 Code | When to Use for PATCH |
|---|---|
| 200 OK | Successful update, returns the updated resource |
| 204 No Content | Successful update, returns no body |
| 400 Bad Request | Invalid data, unknown fields, validation errors |
| 401 Unauthorized | Caller not authenticated |
| 403 Forbidden | Caller authenticated but not allowed to modify resource |
| 404 Not Found | Resource does not exist |
| 409 Conflict | Update conflicts with existing state (e.g. unique email) |
Example success response with updated resource:
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/1.1 204 No ContentExamples of PATCH in a REST API
Example 1: Update a Todo Item
Imagine a todo resource:
{
"id": 10,
"title": "Buy groceries",
"description": "Milk, eggs, bread",
"completed": false,
"priority": "medium"
}Change only the `completed` field
PATCH /todos/10
Content-Type: application/json
{
"completed": true
}Result:
{
"id": 10,
"title": "Buy groceries",
"description": "Milk, eggs, bread",
"completed": true,
"priority": "medium"
}Change `title` and `priority` together
PATCH /todos/10
Content-Type: application/json
{
"title": "Buy groceries and snacks",
"priority": "high"
}Example 2: Partially Updating an Order
Order resource:
{
"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
PATCH /orders/1001
Content-Type: application/json
{
"status": "shipped"
}Change shipping address and status
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:
{
"id": 1,
"full_name": "Alice",
"bio": "Hello",
"is_active": true
}
Client wants to delete the bio text:
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:
- Accept a JSON object with any subset of resource fields.
- For each field:
- If present, validate and update the field.
- If absent, leave the field unchanged.
- Return
200 OKwith the updated resource.
Example for a blog post resource:
{
"id": 5,
"title": "Original title",
"content": "Original content",
"tags": ["python"],
"is_published": false
}PATCH request:
PATCH /posts/5
Content-Type: application/json
{
"title": "Updated title",
"tags": ["python", "backend"]
}Updated resource:
{
"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:
{
"action": "publish"
}It is usually clearer to update the state directly:
{
"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:
- Which fields are updatable with PATCH
- Which fields are read-only
- What happens if a field is omitted
- How to remove or clear optional fields (for example,
null) - Validation rules for each field
This helps clients avoid surprises when using partial updates.
Summary
- PATCH is used for partial updates of a resource.
- Use the same resource URL as GET or PUT, for example
/users/{id}. - Request body usually contains only the fields that should be changed.
- Fields not included are typically left unchanged.
- PATCH is not guaranteed to be idempotent, but you should try to design it that way by setting field values instead of performing "increment" or "toggle" actions.
- Validate only the fields that appear in the request, and return appropriate HTTP status codes.
- For most beginner REST APIs, a simple "partial representation" PATCH is enough and easy to implement.
Views: 8
KAHIBARO