Rest – How to correctly implement key=value storage REST API

apiapi-designrestweb-api

I'm new to REST API, so I decided to get familiar with it by designing a small web service API. I have its design written down and would like you to review it. I feel like I have made some mistakes in designing it and understanding REST concepts, which I try to address with questions on my design at the very end. I'm mostly unsure about my use of URLs for the API.

The web service I try to design provides a way for a user to store key=value pairs, i.e. retrieve value knowing its key, update the value of an existing key and delete an existing key. The whole CRUD set of actions!

Here is what I have came up with.

Versioning

Since my API might evolve, I want a notion of API versions, so I have

GET api.example.com/supported-versions

Which returns a JSON list of integers denoting the API versions supported.

The API will be available at api.example.com/{VERSION}/ endpoint, e.g. api.example.com/1/ for the first version.

Key=value storage

GET api.exmaple.com/1/keys/{KEY}

Allows a user to get a value associated with a key KEY. The server responds with a status code (200, 404, etc.) and a text value on success, both encoded in JSON.


POST and PUT api.exmaple.com/1/keys/{KEY}?value={VALUE}

Allows a user to create/update the value associated with the key KEY. The server returns a status code (200, 404, etc.). VALUE is a text string.

DELETE api.exmaple.com/1/keys/{KEY}

Allows a user to delete a key=value pair with key KEY. The server Which will delete the key=value pair and return a status code (200, 404, etc.).


Let's imagine that there is an OAuth2 authentication set up, which is used for the up above POST/PUT/DELETE methods (but not GET anyone can GET, you don't need authentication for that), so there is a way to uniquely identify a user and keep track which key=value pairs belong to which user.

Now, I want an authenticated user to be able to get a list of all keys they have, so that they don't have to store this information on client-side in order to send DELETE or PUT request later.

GET api.exmaple.com/1/keys?page={PAGE}

This allows a user to get a list of all existing keys they have created. PAGE is an optional parameter. User can increase page count until the user gets an error status code. It returns a paged list of all existing keys a user have created and also a status code (200, 404, etc.).


Is there anything wrong with this API?

Should the first GET/POST/PUT/DELETE from Key=value storage section be on /keys/ or /values/?

Is it fine that the last "GET", the one which returns all keys a user has, is also /keys/?

Best Answer

Your solution is OK, save for a few things:

  1. Versioning REST APIs at the resource level is generally not a good practice, although this not necessarily a consensus view. See here for some comments and links to further discussion.

  2. To your second question, you could probably argue either way as to whether /keys/{id}/ or /values/{id}/ is correct, but my instinct would be to either use keys since it's the "parent" of the tuple, or I'd use an entirely different name such as /data/ or /elements/, or whatever it is these things actually represent.

  3. I would probably have different GET methods for the whole key-value dictionary, e.g. /keys/{id}/, and a separate resource for those for a particular user, e.g. /users/{id}/keys/{keyId}.

Finally, it's not great (although possible) to use query strings with POST/PUT/DELETE methods. It is a query string, after all. Instead, you could use POST /data/, and put the key-value pair as JSON data in the request body. See this question as well.