IPA-109: Custom Methods
Resource-oriented design uses custom methods to provide a means to express arbitrary actions that are difficult to model using only the standard methods.
Guidance
Custom methods should only be used for functionality that cannot be easily expressed via standard methods
- Prefer standard methods if possible, due to their consistent semantics
paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupCluster
summary: Pause a cluster
parameters:
- name: groupId
in: path
required: true
schema:
type: string
- name: clusterName
in: path
required: true
schema:
type: string
responses:
"200":
description: The paused cluster.Why:Pausing a cluster is a state transition with side effects, not a field edit or a read. No standard method captures it, so a custom
:pauseis justified.paths:
/groups/{groupId}/clusters/{clusterName}:setName:
post:
operationId: setGroupClusterName
summary: Set the name of a cluster
parameters:
- name: groupId
in: path
required: true
schema:
type: string
- name: clusterName
in: path
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
name: { type: string }
responses:
"200":
description: The updated cluster.Why:Setting a field is a partial update of an existing resource, which the standard Update method already covers. A custom
:setNameverb provides none of Update's consistent semantics and tooling that knows the standard methods can't see what the call does.Identify the custom method by its
:verbsuffix in the path (e.g./groups/ {groupId}/clusters/{clusterName}:pause).Read its summary, request body, and response to work out what state it reads or changes, and on which resource.
Ask whether that intent maps onto a standard method: retrieving one resource (Get), retrieving a collection (List), creating a resource (Create), modifying an existing resource's fields (Update), or removing a resource (Delete).
If the intent fits a standard method, flag it — the standard method should be used instead. The custom method is fine only when no standard method captures the behavior.
The name of the method should be a verb and may be followed by a noun
paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupCluster
/groups/{groupId}/clusters/{clusterName}:addNode:
post:
operationId: addGroupClusterNodeWhy:pauseis a bare verb;addNodeis a verb followed by a noun. Both name an action, which is what a custom method represents.Read the custom method name from the path section after the colon (
:).Confirm the name begins with a verb describing the action performed.
Flag any custom method whose name is not a verb (for example a bare noun or adjective).
The HTTP method must be
GETorPOST:GETmust be used for methods retrieving data or resource state.POSTmust be used if the method has side effects or mutates resources or data
paths:
/groups/{groupId}/clusters:search:
get:
operationId: searchGroupClusters
summary: Search clusters
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupCluster
summary: Pause a clusterWhy::searchonly reads data, so it usesGET.:pausemutates the cluster's state, so it usesPOST. The HTTP method matches whether the call reads or changes state.paths:
/groups/{groupId}/clusters/{clusterName}:pause:
put:
operationId: pauseGroupCluster
summary: Pause a clusterWhy:A custom method must use
GETorPOST.:pausehas side effects, so it must usePOST;PUTis not a permitted HTTP method for a custom method.Custom methods using the
GETHTTP method must return a 200 OK response.paths:
/groups/{groupId}/clusters:search:
get:
operationId: searchGroupClusters
summary: Search clusters
responses:
"200":
description: The matching clusters.Why:The
GETcustom method:searchretrieves data and documents a200 OKresponse, the expected success status for a read.paths:
/groups/{groupId}/clusters:search:
get:
operationId: searchGroupClusters
summary: Search clusters
responses:
"204":
description: No content.Why:A
GETcustom method retrieves data, so it must return200 OK. A204 No Contentadvertises that the read produces no body, which contradicts the purpose of the method.The HTTP URI must use a colon(:) character followed by the custom method name
- This aims to clearly distinguish between custom methods and other resources
- The custom method name must be written in
camelCase
paths:
/groups/{groupId}/clusters/{clusterName}:addNode:
post:
operationId: addGroupClusterNodeWhy:The custom method is appended to the resource identifier with a colon, and
addNodeiscamelCase. The colon clearly separates the custom method from the resources in the path.paths:
/groups/{groupId}/clusters/{clusterName}/add-node:
post:
operationId: addGroupClusterNodeWhy:add-nodeis appended as a path segment rather than after a colon, so it reads as another resource instead of a custom method, andadd-nodeis notcamelCase.
See Declarative-friendly resources for further guidance
Example
POST /groups/${groupId}/clusters/${clusterName}:pause
GET /groups/${groupId}/clusters:search
POST /groups/${groupId}/clusters/${clusterName}:addNode
POST /groups/${groupId}/clusters/${clusterName}:removeNode
Naming
Operation ID must be unique
paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupCluster
/groups/{groupId}/clusters/{clusterName}:addNode:
post:
operationId: addGroupClusterNodeWhy:Each operation has its own distinct
operationId. Unique operation IDs let generated clients expose one unambiguous method per operation.paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: clusterAction
/groups/{groupId}/clusters/{clusterName}:resume:
post:
operationId: clusterActionWhy:Two operations share the
operationIdclusterAction. A duplicate operation ID collides in generated code, where one method name would have to stand for two different operations.Operation ID must be in
camelCasepaths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupClusterWhy:pauseGroupClusteriscamelCase, matching the convention used for operation IDs across the API.paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pause_group_clusterWhy:pause_group_clusterissnake_case, notcamelCase, breaking the operation ID naming convention.Operation ID must start with the custom method verb
- Derived from the path section delimited by the colon (:) character
paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupClusterWhy:The custom method verb is
pause(the path section after the colon), and the operation IDpauseGroupClusterstarts with it.paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: groupClusterPauseWhy:The verb
pausefrom the path is buried at the end ofgroupClusterPauserather than leading it. The operation ID must start with the custom method verb.Take the path section after the colon (
:) — this is the custom method verb (for example,pausein:pause).Confirm the
operationIdbegins with that verb.Flag any operation ID that does not start with the custom method verb.
Operation ID should be followed by a noun or compound nouns
paths:
/groups/{groupId}/clusters/{clusterName}:pause:
post:
operationId: pauseGroupClusterWhy:After the verb
pause, the operation ID continues with the nounsGroupCluster, naming what the action applies to.- Strip the leading verb from the operation ID.
Confirm what remains is a noun or compound nouns describing the target of the action.
Flag an operation ID that is a bare verb with no following noun.
The noun(s) in the Operation ID should be
- The collection identifiers from the resource identifier in singular form
- The custom method noun(s)
- Derived from the path section delimited by the colon (:) character
paths:
/groups/{groupId}/clusters/{clusterName}:addNode:
post:
operationId: addGroupClusterNodeWhy:The nouns in
addGroupClusterNodeare the singular collection identifiers from the path —groups→Group,clusters→Cluster— followed by the custom method nounNodefrom:addNode.List the collection identifiers in the resource identifier (for example
groupsandclusters) and put each in singular form.Take any noun(s) from the custom method name in the path section after the colon (
:).Confirm the operation ID's nouns are composed of the singular collection identifiers followed by the custom method noun(s).
Flag an operation ID whose nouns do not derive from the resource identifier and the custom method name.
| Resource Identifier | Operation ID |
|---|---|
/groups/${groupId}/clusters/${clusterName}:pause | pauseGroupCluster |
/groups/${groupId}/clusters/${clusterName}:addNode | addGroupClusterNode |
/groups/${groupId}/clusters:search | searchGroupClusters |
Declarative-friendly resources
Declarative-friendly resources should not use custom methods. To learn more, see IPA-127.
- Custom methods require manual curation, implementation, and review for API tooling, which increases feature latency.
- Declarative-friendly tools are unable to automatically determine what to do with them
Determine whether the resource is declarative-friendly (see IPA-127).
Look for custom methods (paths with a
:verbsuffix) on that resource.Flag any custom method on a declarative-friendly resource, since declarative tooling cannot automatically determine what to do with it.
State transitions that carry side effects are usually good candidates for custom methods