2

How do I name API endpoints that serve the same entity in different ways and still adhere to the RESTful API guidelines?

Let's consider I'd like to get a customer with ALL his details.

  • I just expose a GET endpoint at address "/customer".

Now I'd like to check if a customer with a particular customerId exists.

  • What do I do now? How do I name the endpoint?

Possible solutions I've thought:

  • I expose another GET endpoint at address "/customerNameCheck". This feels SOAP-y.

  • I keep the GET endpoint at address "/customer" which accepts an extra parameter called type which could take values type="check"/type="fullCustomer" which will determine the flow of events on the server and serve the appropriate response.


Both of my solutions feel like violations of general naming conventions.

Any ideas?

5
  • How do you know your whose details to return in your first example? It should be GET /customer/{customerId}. If it exists you see all their details, if not the customer doesn't exist.
    – imel96
    Jun 30, 2016 at 3:46
  • @imel96 You're right, it's a typo actually. The problem is exactly what you state though. Why would i want ALL the details of the customer if all I want to know is if he exists or not? Jun 30, 2016 at 4:01
  • You can use HEAD request to check if the ID exists. I'm curious though, why do you want to check for an ID?
    – imel96
    Jun 30, 2016 at 4:30
  • @imel I don't, it's just an example for the concept Jun 30, 2016 at 4:31
  • The issue is you start at the end. If you already know the url you just get a 404 does not exist error. Then you know it's now there (anymore). But the thing is your first got that url. In most cases if your work with HATEOS or other linking schema's you will not get links to non existing resources. Jun 30, 2016 at 7:57

4 Answers 4

6

As per comments, the URL to get details of a customer is /customer/{customerId}.

To check if a customer ID already in use without retrieving all the details, you can query the same URL using a HEAD request.

3

A fields parameter can take care of this.

  • In the example given in the question we could simply ask for the customerID field.

  • If the response provides a result then it exists.


From Best Practices for Designing a Pragmatic RESTful API by Vinay Sahni

Limiting which fields are returned by the API

The API consumer doesn't always need the full representation of a resource. The ability to select and choose returned fields goes a long way in letting the API consumer minimize network traffic and speed up their own usage of the API.

Use a fields query parameter that takes a comma separated list of fields to include.

Example:

GET /customer?fields=id,subject,customer_name,updated_at

2

Now I'd like to check if a customer with a particular customerId exists. What do I do now? How do I name the endpoint?

You don't.

REST is about state transfer. You transfer a representation of the resource between the client and server (REpresentational State Transfer).

You don't put domain specific logic into your URL scheme. A resource has a URL, and that is. You don't use URLs to start running procedures on the sever (eg hey server check if this customer exists)

That is moving into RPC territory, and is the opposite of what REST is trying to give you.

Why would i want ALL the details of the customer if all I want to know is if he exists or not?

REST doesn't concern itself with "why" the client wants the resource. That isn't for the URL scheme to manage. The client might want the resource just to see if it exists, it might want to see if the customer is from Washington, it might want the resource to see if the customer joined in the last year, etc etc

Your URL scheme doesn't care. This is on purpose, cause imagine if your URL scheme did care. You would end up with URL scheme expressing some sort of domain specific query language.

It is far easier to just get the resource and let the client figure out what conclusion it draws from the current state of the resource.

If you have a resource that is massive and your client would like the representation of this resource in another format, you can use the Accept and Content-Type headers to negotiate between the client and the server a format that the client wants. For example you might have a representation of the Customer that has the entire customer data, and one that just has ID and name. The client can say it accepts this short format and the server can return it.

Though to be honest unless your resource is massive I wouldn't even bother with that.

1

Normally in REST your would get:

/customers -> List of customers (We include links here in HATEOS so in this JSON you will find link to /customers/123)
/customers/123 -> Full details of customer 123 (you can limit fields if you want)
/customers/9999 -> If this customer does not exist return error 404

So as you see you would never get a link to /customers/9999 in /customers because it does not exist. So you would not encounter a missing customer a lot of times.

It can happen though, for example if you cached a link to customer 100 and it gets deleted. In that case the API client receives an error 404 which is a permanent error and it will clear it's cache so it will not happen again.

Your question:

How do I name API endpoints that serve the same entity in different ways and still adhere to the RESTful API guidelines?

In general you won't. What you have is a resource, let's say a customer in this case. That resource can be represented in multiple ways. For example you could do:

/customers/123.json
/customers/123.xml
/customers/123.pdf

Same customer, same url, but different representation. You can do this by using content-type detection so you don't have to use extensions if you want.

For the same customer you only want a single url. Not multiple endpoints, that's not a strategy for the future. REST strongly works with error codes to respond the right answer to your client. That's what prevents the need for things like:

I keep the GET endpoint at address "/customer" which accepts an extra parameter called type which could take values type="check"/type="fullCustomer" which will determine the flow of events on the server and serve the appropriate response.

You just don't need that in REST.

1
  • I was wrong in my comment above - sorry and thanks:) Jun 30, 2016 at 10:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.