JSON-API expects me to provide an id
with the resources we create and move around. But how do we handle cases where the resource doesn't have a natural ID?
A good example is a quote system where the price needs to be determined server side. In this case, we don't give the client the price-book to work out the price themselves, the client needs to submit something to the API so the server can determine the price.
However, we don't want the quote to be persisted to a DB yet because it is not technically "locked in", the client is just playing with options before proceeding"
One way I thought of is to create a UUID for the quote in the pending state
For example
POST /quotes
{ "data": { "type": "quotes", "attributes": {
"state": "pending", <all the items>
} }
returns
{ "data": { "type": "quotes", "id": <UUID>, "attributes": {
"price": 900, "state": "pending", <all the items>
} }
Now I have the price in the response but I can't get it at a defined url like /quote/1234 yet.
Then once state updates to "quoted" I can physically save to DB, get a proper ID and the client can GET /quote/1234 to see the submitted quote and its price.
The alternative is to create intent resources that model the intention to get a price or fulfil some workflow. I just don't know how you would implement that within a JSON-API context because, again, there aren't IDs.
How should one handle these dynamic/calculated/ephemeral resource endpoints?
I would create a separate table for these pre-quote requests. I can think of several reasons why you would want these captured in a DB, you can have all sorts of metrics like how many times they played with the options, during what time, how long did it take them to create an actual quote etc etc. You can then limit those requests, you can stop the spam of such requests etc.
Once a pre-quote becomes an actual quote, at that point you can move the data to your Quotes table and can use the API properly, because you now have IDs from pre-quotes you can work with. It seems to me that you simplify everything if you just store those in the DB and assign them a proper ID from the beginning.