"remote-triggers" maybe a profile?

Our API needs the client to execute some non-RESTful stuff on resources. An example is “notify” which would send emails to specific people about the resource, another example is a change of state (that might not be successful and should be atomic, not seen as part of an update - state itself is readonly from the point of view of the client).

I have thought about the following, which I’m not sure it is compliant or even reasonable. I would really like feedback before continuing this path.

URIs

The triggers would have the following URI scheme:

https://example.com/resource-type/ID/triggers/notify

A POST to the trigger URI would attempt the trigger, returning either OK (what content?, just “202 Accepted” with a dummy JSON body would be enough?) or error (standard documented error responses would do here)

POST to the trigger MAY include meta (for multifactor authentication or other) and even data (for last-moment changes to the resource that NEED to be done atomically with the trigger).

A GET to the trigger URI would “dry-run” the trigger, but possible errors should be returned anyways. This answers to a client that wants to know if the trigger is available, as the preconditions for the trigger might not be known in advance by the user. In a possible client UI, an error response to this GET could prevent a button to be shown.

Links

In the triggerable resource, the links member would contain the trigger links:

"links": {
  "self": "https://example.com/resource-type/ID",
  "notify": "https://example.com/resource-type/ID/triggers/notify",
  "proceed": "https://example.com/resource-type/ID/triggers/proceed"
}

When a client expects a trigger to be present, but it is not found in the resource links, it can GET the trigger to obtain (and react to) the reason that caused the trigger not to be present:

"links": {
  "self": "https://example.com/resource-type/ID"
}

GET https://example.com/resource-type/ID/triggers/notify
{"errors": [{"status": "502", "code": "mailserver.down", "title": "Mail subsystem temporarily offline"}]}

GET https://example.com/resource-type/ID/triggers/proceed
{"errors": [{"status": "403", "code": "unauthorized", "title": "Only administrators can proceed"}]}

Should all this be a profile? Can a profile encompass URIs? Are non-dashed URI reserved for future use like the query params? Are non-dashed link names reserved for future use?

1 Like