As REST is just a generalization of the interaction concept used in the browsable Web, the problem definition can be transformed to "How would you attempt something like that on the Web" and then use the concepts applied for the Web and translate it to the application domain.
On the Web typical CRUD operations are usually achived with a mixture of links, Web forms and images that express some meanings and affordances to us humans. I.e. an edit
action usually is depicted with a pencil symbol that upon clicking will render a pre-filled form representation that sends the updated content after pressing a further submit button to the server. Due to the limitations of HTML forms such requests are usually issued as HTTP POST operations.
The affordance now expresses what can or should be done with certain items.
Affordance is a property or feature of an object which presents a prompt on what can be done with this object. In short, affordances are cues which give a hint how users may interact with something, no matter physical or digital (Source)
Mike Amundsen and Asbjørn Ulsberg also explained this concept. Such affordance can either stem from things typical in the real-world, i.e. if you want to remove something from your belongings you throw it into a waste bin as such a waste bin symbol may express a removal, or from domain-specific knowledge, certain standards or ontologies. Think of how pagination is usually achived on the Web. Here you usually have symbols like <<
, <
, >
or >>
that express the actions of paging one or multiple pages forwards or backwards.
As REST targets at applications rather than humans, who easily can sense the meaning and affordance of things, a computer will prefer some less ambigious approaches, such as standardized relation types, domain specific knowlege, ontologies or even microformats. Such relations usually make use of Web linking extensions and may also be specified in media-type format descriptions. For paginations i.e. IANA defines prev
, next
, first
and last
instead of relying on certain icons that may look different from Web page to Web page. Such link relations howeve are not only used for navigation, they are also used to give clients a hint on when certain resources may be requested. Think of HTTP/2 PUSH including prefetch
annotated links or HTTP Preload instructions, while they may behave similar they are though a bit different (Further read).
A promotion of an employee can be seen as an update to the employee's state and as such, as mentioned before, a form-like representation might be used that offers a client choices it can select from. A link offering such a promotion may be annotated with edit-form http://api.acme.com/relation/promotion
, where edit-form
hints a client that upon invoking that link a form representation will be returned and the custom Web link http://api.acme.com/relation/promotion
hints the client about the special purpose of that resource. It might not really know what this URI expresses, and the URI itself does not need to expose a documentation on the purpose itself, the link-relation is just an arbitrary string to the client after all, though it might add special support for such link-relations in future or in a dedicated media-type.
Exposing an own edit-form is especially convenient if there is not a strict hierarchical structure and the employee can be promoted to a totally different position, which also does happen in practice. A promotion might also only be salary-wise or by adding certain benefits. As such allowing one admissible person (or automated service) to alter the configuration is for sure a future-proof way.
In recent years there have been a couple of approaches on form-like representation formats. The probably best known is for sure HTML with its forms definition, though a couple of JSON based approaches such as HAL-Forms, halform or ion evolved, though they are still more or less in draft-phase and not final, at least they currently lack widespread support.
Note that this post so far didn't talk about the actual form of the URI, as this is not relevant in a REST architecture as clients shouldn't attempt extracting knowledge from URIs as the server is free to change its URI-scheme at any time. A client extracting knowledge from URIs directly is highly likely to break when a server chagnes its URI scheme and that is usually a bad thing in remote computing for services that are meant to stay around for years to come and evolve in future. As such I don't agree with the other proposals here so far that more or less promote the usage of a certain URI in combination with a HTTP method. We humans also don't want to read the URI and prefer an accompanying, human-readable text that summarizes the linked content.
How should I do this in a "restful" manner?
REST is all about decoupling clients from servers to allow servers to evolve freely in future and make clients more robust to changes and using a server-teaches-client-what-it-needs-approach. One therefore should use the Web as an example on how to model the interaction in a REST architecture. Fielding made things like HATEOAS (the usage of links and forms) as well as caching, statelessnes and other properties a constraint and not an option. Therefore you will only benefit from a REST architecture if you adhere to these constraints stringent.
As such, the introduction of a dedicated edit form to alter the state of the employee does make sense and allows updates in the future. The form itself is usually exposed as an own resource, that is cacheable, and will target the actual resoure, which upon submitting the data via an unsafe method (may be defined by the media-type, as HTML does, or via a property on the element itself) will evict any cached representations for that resource so that a consecutive GET request is able to fetch the new data instead of any outdated cached data. This is tightly related to caches using the de-facto URI as key for caching response content and evicing those stored data if an unsafe request is performed on that URI.
By supporting multiple form-representation formats you just increase the likelihood that an arbitrary client is able to interact with your service as clients and server should make use of content-type negotiation anyways to increase interoperability chances.
By using link-relations you can hint a client on the purpose of a certain link and let a client decide whether that link is of interest at the current state the client is in. This basically allows the server to change the URI scheme any time it wants to but allows clients to still know the purpose of the URI by just looking at the link-relation.