As others have pointed out a RESTful API should expose resources (nouns) rather than actions. See Representational state transfer (Wikipedia).
But I understand that your question is about the granularity of the resources that the API exposes.
Let's take your contact and its email property for example. We'll start by creating a contact:
POST /contact
{"name": "John Doe"}
(Please forgive a tangent since it's completely unrelated to your question, but I suggest not splitting names into first
and last
unless you absolutely have to and here's why).
This returns a new contact_id
of 17.
So now the real question is, do we add a phone number to John like this?
PATCH /contact/17
{"phone": "555-5555"}
...or like this?
POST /contact/17/phone
555-5555
Reflect the data model?
I think one determinant may be your underlying data model.
If you have a contact database schema that looks like this:
=====================================
contact
=====================================
contact_id name phone
-------------------------------------
17 john doe 555-5555
Then I think the single /contact
resource makes the most immediate sense.
But if your database schema allows for a one-to-many relationship with phone numbers like this:
========================
contact
========================
contact_id name
------------------------
17 john doe
===================================
phone
===================================
phone_id contact_id number
-----------------------------------
243 17 555-5555
Then the more granular resource, /contact/17/phone
, suddenly seems sensible. (After it's been created, this specific phone number would be at /contact/17/phone/243
on which you could act with HTTP verbs PUT or DELETE).
Of course, your API resources do not need to (and often should not) reflect your underlying data model. Both database schemas could be reflected just fine with either API structure. But it can be
Other considerations:
- The API can hint at the way it should be used by the way its structured.
/contacts
and /contacts/{id}/phone
may allow the same functionality, but they give the end API's consumer a different impression!
- More granular APIs can conceivably allow you to create more efficient services by allowing you to write very specific bits of code at the expense of more code.
/contacts/{id}/phone
can be written very simply - but you are now saddled with the overhead of writing and maintaining (and documenting!) this resource for the lifetime of the API
- You can add more granular resources while keeping backwards compatibility, but you cannot take them away! So if you're on the fence, consider starting off coarse and adding finer grain as needed!
Also somewhat tangential to your actual question is how to deal with this tricky relationship in REST:
- associateContactWithGroup?contactId=x&groupId=y
You can either allow /contact/17
to take a {"group":"34"} property in an update. Or you can create a /contact/17/group
resource. (This could serve a one-to-one or many-to-many relationship with groups, which would look very similar.)
The interesting thing is that you may also want to expose this from the groups point of view with resources like /group/34/contacts
. There's no wrong answer, but consider having as few resources as you can get away with to start. You can always add more in a backward-compatible way later!