Update Endpoints (#134)
From 2023-01-10 until 2025-04-08, Kong's guidance was to provide PATCH
endpoints only. This was changed on 2025-04-08 to require PATCH
and PUT
for all endpoints. This is not being retroactively enforced for existing APIs.
Both PATCH
and PUT
operations are required1 for entities. PATCH
operations are user-friendly for end users that are directly implementing the API in their applications, and PUT
operations are required to build fully declarative tooling.
1 If you believe that your API can't support both operations based on the exceptions listed below, seek approval in the #api-design channel in Slack
PATCH
Endpoints used to update an entity should use PATCH
as the verb rather than PUT
. This allows for partial updates of the resource. (We require users to use the POST
endpoint for entity creation).
PATCH
endpoints in OpenAPI specifications should use the operation ID update -<entity>
e.g. update-control-plane
.
PATCH
endpoints must implement a derivative of JSON Merge Patch as defined by RFC 7396 with the following clarifications:
- If the
Content-Type
request header is not application/json
, the PATCH
operation must return 400.
- If an unknown field is provided, the entire
PATCH
operation must return 400 with the unknown field described in the invalid_parameters
extension.
- If a read-only field is provided, the entire
PATCH
operation must return 400 with the read-only field described in the invalid_parameters
extension.
- Nested object fields MUST be recursively patched.
- If the value of a field in the patch document is set to
null
and...
- If the property is non-required, then remove the property from the object.
- If the property is within a schema-less object, then remove the property from the object.
- If a property is required and nullable, then set the value of the property to
null
.
- If a property is required and non-nullable, then return 400 with the required property described in the
invalid_parameters
extension.
Examples
Given the following example JSON document:
{
"a": "b",
"c": {
"d": "e",
"f": "g"
}
}
If we apply the following changes:
PATCH /target HTTP/1.1
Host: example.org
Content-Type: application/json
{
"a":"z",
"c": {
"f": null
}
}
The preferred JSON response would include any nullified fields that are defined in the entity's schema:
{
"a": "z",
"c": {
"d": "e",
"f": null
}
}
An acceptable JSON response would be to leave out null fields, but this should be the exception, not the rule, for Kong APIs:
{
"a": "z",
"c": {
"d": "e"
}
}
Detailed Examples
Given the following JSON document:
{
"attr_1": "Sample Entity",
"attr_2": false,
"attr_3": {
"sub_attr_1": "red",
"sub_attr_2": 1337
},
"tags": ["tag_1", "tag_2"],
"labels": {
"key_1": "val_1",
"key_2": "val_2"
}
}
Add a value
Add "attr_4": "New Attribute"
:
{ "attr_4": "New Attribute" }
Update a value
Change "Sample Entity"
to "Updated Entity"
:
{ "attr_1": "Updated Entity" }
Add a nested field
Add a new attribute, sub_attr_3
to attr_3
:
{ "attr_3": { "sub_attr_3": "yellow" } }
Update a nested field
Change "sub_attr_1"
to "blue
" in "attr_3"
:
{ "attr_3": { "sub_attr_1": "blue" } }
Setting a nullable field to a null
value
{ "attr_3": null }
Replace an array
Replace the tags
array with a new one containing "tag_3"
and "tag_4"
:
{ "tags": ["tag_3", "tag_4"] }
Empty an array
{ "tags": [] }
Delete a field from an object
Remove the label "key_2": "val_2"
from the labels
object:
{ "labels": { "key_2": null } }
Remove all fields from an object
You must provide all existing keys and specify a null
value to remove all of them:
{ "labels": { "key_1": null, "key_2": null } }
No-op requests
The following patch requests perform no updates.
{}
{ "labels": {} }
{ "attr_3": {} }
hello
PUT
PUT
can either create or replace an entity based on rfc-7231. In the case of a creation, the endpoint MUST return 201
. When the entity is replaced, the endpoint MUST return 200
.
PUT
endpoints in OpenAPI specifications should use the operation ID upsert-<entity>
e.g. upsert-control-plane
.
Example
PUT /entity/{id}
PUT /entity/123 => HTTP 201. entity created
PUT /entity/123 => HTTP 200. entity replaced
Security: Enumeration risks
When the endpoint supports the creation of an entity the implementation MUST ensure the ID
of the resource passed is only unique within its parent and organization. This implies that these IDs cannot be a globally unique primary key within a relational database schema. Otherwise it makes entity enumeration possible.
See example:
PUT /parent/{id-1}
PUT /parent/{id-1}/child/{id-2}
PUT /parent/1 => creates parent:1 in organization A
PUT /parent/1 => creates parent:1 in organization B
PUT /parent/1/child/2 => creates child:2 in parent 1 in organization A
PUT /parent/3/child/2 => creates child:2 in parent 3 in organization A
PUT /parent/1/child/2 => creates child:2 in parent 1 in organization B
PUT /parent/3/child/2 => creates child:2 in parent 3 in organization B
In the example above we see that none of the IDs created by PUT
requests collides between orgs or parent entities.
Exceptions
PATCH is not suitable
PATCH
operations may be omitted when the full entity representation is required to validate the data sent in the request (ex: conditional entity representations based on a type
property discriminator).