How to improve my REST API? - api

I have some questions regarding my REST API that's still in development.
I have the following endpoints:
/users.json: shows a list of all the users
/users/$username.json: shows a single user resource
/posts.json: shows a list of all the posts
/posts/$post_id.json: show a single post resource
A single post resource looks like this:
{"path": "http://api.myproject.com/posts/1.json", "id": 1, "author": "http://api.myproject.com/users/kristof.json", "image": "/images/posts/cxyUzlPo.jpg", "date": "2014-11-09 15:16", "likes": "http://api.myproject.com/posts/1/likes.json", "comments": "http://api.myproject.com/posts/1/comments.json", "likes_count": 0, "comments_count": 0}
As you can see, a post contains a field "author", which defines a hyperlinked relationship to a single user resource.
Now the following problem occurs: I want to build a feed of all the posts created by users. That's easy: I just call the /posts.json endpoint and I have all my posts... But when I want to show the author information about every post, then I would have to make an extra HTTP REST call for every post in the list? That seems very inefficient and bad for performance to me?
Now of course, you can also add the author resource as a nested resource in the list of post resources, but is this still regarded as "RESTful"?
The longer I'm busy building REST APIs (the more I'm learning, obviously), but the more I have to make decisions between "pragmatic REST" and "REST as a religion". :-)
Thanks in advance for any help!
Kind regards,
K.

You can include author information for every post in a call to /posts/ and it's still RESTful. The issue then becomes how to include this information. Please have a look at JSON HAL and read about embedded resources.

Related

RESTful way of referencing other resources in the request body

Let's assume that I have a resource called group with the following representation:
{
"id": 1,
"name": "Superheroes"
"_links": {
"self": {
"href": "http://my.api.com/groups/1"
}
}
}
Now let's say I want to create a new person instance by POSTing to /persons/1. Which of the following should I use for the request body:
Using ID
{
"name": "Batman",
"groupId": 1
}
Using link
{
"name": "Batman",
"group": "http://my.api.com/groups/1"
}
With the first method I access the id directly either to look up the related resource or eventually store the id in the database, when I persist the person instance. But with the other method, I either have to extract the id from the URI or, follow the link to load the related resource, and then find out its id. I really don't want to store the URI in the database.
With the latter option, seeing that the server controls the structure of the URI, is it fine for me to parse the id out of the link? Following the link back to the server itself seems odd, seeing that at this point we already have access to the information directly (we just need the id).
So to sum up, which of these options is best?
Use the id directly.
Use the link, but parse out the id.
Use the link, but access the link to get the resource instance, and then get the id.
TL;DR: Use simple ids.
More detailed explanation:
A straightforward approach is to create a person by POSTing to /groups/1/persons with a payload {"name": "Batman"}.
However, while such approach works for simple cases, the situation gets complicated if there are 2 resources that need to be referenced. Let's assume that a person also needs to belong to exactly one company:
GET /persons/1
{
"name": "Batman",
"group": 1, // Superheros, available at /groups/1
"company": 5 // Wayne Enterprises, available at /companies/5
}
Since there is no relationship between companies and groups, it is not semantically correct to create a person via POSTing to /groups/1/companies/5/persons or to /companies/5/groups/1/persons.
So let's assume you want to create a person with a request looking like this:
POST /persons
{
"name": "Batman"
"group": ???, // <--- What to put here?
"company": ??? // <--- What to put here?
}
Which brings us to the answer to your question:
Ease of use. Your API should be primarily designed for the ease of use. This is especially true, if you design a public API. Therefore, Option 2 (Use the link, but parse out the id) is out, since it imposes additional work for clients of your API.
Constructing search queries. If you want to be able to query persons which belong to the company 10 and the group 42, simple ids lead to more readable and less error-prone urls. Which of the following do you consider more readable?
URL with a simple id:
GET /groups/42?company=10
or URL with a url-encoded link:
GET /groups/42?company=http%3A%2F%2Fmy.api.com%2Fcompanies%2F10
I wouldn't underestimate the point of readability. How many times do you need to debug your API in various curls, logs, postmans, etc.
Development Links need to be parsed in the backend, while simple ids can be used directly. It's not about performance, but rather about additional work/tests you have to put in.
Endpoint maintenance. Imagine that your API endpoint evolves. You decide one day to switch to https or to include versioning in the url. This might break API clients, if they for some reason rely on structure of the links. Also, you might want to checkout if link parsing on your backend is done properly.
Argumentum ab auctoritate I know this is not a proper argument, but if you checkout APIs of large players, e.g. Twitter, Github or Stripe, they all use simple ids.
HATEOAS. One common argument in favour of links is that it is aligned with HATEOAS. However, as far as I know, this relates to additional links in API responses rather than using links in payloads of POST requests.
All in all, I would go for simple ids, since I haven't yet heard a compelling argument favouring links, which would beat the aforementioned.
You are missing two important things here.
You need a standard way to describe forms in the response, in this case your POST form.
The information about the group ids / uris, or how to get them has to be described in the form in a standard way.
For example a HTML FORM with a SELECT INPUT would be RESTful. The closest thing we got in json to do the same is json-ld and hydra. But if you are obsessed with hal, then use hyperagent forms or something like that. It will never be a standard, but if compatibility is not an issue, then it is good enough.
To answer your question, you should use the id, because the server knows how to interpret it. The client needs the resource identifiers, the server needs it only in the uri part of the request, not in the body.
From my experience, it is always best to go with the simplest solution for making requests.
The process of generating a new url and parsing it seems excessive to get a resource, whereas sending the id of the item you want seems much simpler.
Thus, I would send a request in the form:
{
"name": "Batman",
"group": 1
}

What does "consume an API" mean?

Here is an excerpt from an assignment I am currently doing:
Build a dummy app that:
Contains a REST API that operates over a single resource.
Contains a Backbone client that consumes that API and can list, show, create, update, and remove that resource.
My understanding was that the term "consume" implies total coverage of the API's exposed ressources. However, the assignment says "consumes that API and can [CRUD] that resource".
Is that sentence redundant or is my understanding of the term wrong?
(Bonus question: why searching Google for this question returns countless language-specific tutorials for "consuming an API" but none explain what the term actually means?).
To consume an API means to basically use any part of it from your application.
Consuming an API here means creating a client which can send requests to the API that you build.
It appears that you need to create and API which can handle Create, retrieve, update and delete (CRUD) of a resource. For instance if your REST api is to create a blog, your API should handle CRUD functions for the object/resource blogpost.
POST - Create a blog post
GET - Retrieve a blog post
PUT - Update a blog post
DELETE - Delete a blog post.
It is about the direction of the app's interaction with API - it either provides an API, or consumes it, so there are providers and consumers of API, and this is just a less general and ambiguous term than 'using'.
Simply consuming an API means using it in your application.
For, e.g., GET request to https://someapi/Users will give you all the users.
You need to request this URL https://someapi/Users to get all the users and then you can use it into your application.
I always think about Albert Einstein's quote of "If you can’t explain it to a six year old, you don’t understand it yourself." when someone asks a question that you might take for granted due to technical experience you have on a subject.
I think the following medium.com article does an excellent job explaining it: How do you explain API to a 5-year-old?
simply means : using the API.
You can do it with HTTP method (GET, POST, PUT, DELETE..) using something like Postman (Tool) or maybe you have a client app/library that calls these methods implicitly.

Conventions for adding child objects via API (JSON) - Thin URL/Fat Body, or vice-versa?

Say you have an api method that POSTS shelves to a wall:
POST /api/shelve {wallId: 0, shelveTitle: "a shelve for my favorite books"}
And then you have another method that POSTS a book to a shelve:
POST /api/book {shelveId: 0, bookTitle: "my book"}
In terms of syntax and usability, would you rather have the above (thin URL, fat body), or a more verbose URL like this:
POST /api/shelve/0/book {bookTitle: "my book"}
I'm tempted to just keep the URL as simple as possible by saying /api/book and delegate all specification / definition to the body, restricting the URL to verb/noun pairs. I'm brand new to APIs and want to make sure I get off on the right foot... what's the convention in this scenario?
Personally I would go with
POST /api/shelve/0/book {bookTitle: "my book"}
because it's clear that you are adding a book to a shelve, rather then just adding a book.
Opinions vary on REST design, but I can really recommend this small, free book: Web Api Design

Some general restful api design questions

A few general design questions:
Give the example here:
https://developers.google.com/+/api/latest/activities/list#nextPageToken
Why would the server return a token to retreive the next paginated result? Doesn't this break the idea of being stateless?
Why not just pass a MySQL like LIMIT name=value as the parameters? The server now has to return the number of pages I suppose...what am I missing?
I read many but this one was of interest:
REST Web Services API Design
The second reply, offers the following examples.
GET http://api.domain.com/user/<id>
GET http://api.domain.com/users
PUT http://api.domain.com/user/<id>
POST http://api.domain.com/users
DELETE http://api.domain.com/user/<id>
Makes sense but why are there two plural resources? Could one not assume that if "user" is queried and was NULL or not provided that "all" was intended? Likewise for POST? If plural is for improved readability - why is there not a "users" resource for DELETE?
Ultimately, I understand REST to mean...representation of a single resource - using HTTP verbs (GET, PUT, POST, DELETE) to essentially manage that resource - similar to CRUD.
EDIT | Lastly I also wanted to ask why Google API sends the API version in the URI instead of using HTTP headers? Is there a reason? For backwards compat with older clients?
Comments?
Why would the server return a token to retrieve the next paginated result? Doesn't this break the idea of being stateless?
Using this kind of mechanism for paginated result sets is completely standard and does not break the idea of being stateless. Consider the following example.
Suppose GET /users?after=<after> (where after is optional) is supposed to return the list of all users in a paginated fashion, say <= 4 per page.
The first request a client makes is GET /users with a response that might look like the following (formatted as JSON).
{
"users": [ "alex", "bob", "carter", "dan" ]
"more_after": "dan"
}
In this example, the more_after property designates there may be more users left in the user list. So the client then requests GET /users?after=dan and gets a second response that looks like the following.
{
"users": [ "edward", "frank" ]
}
The absence of the more_after property designates that this is the last page of users.
Now the question is: was the "dan" token used as the page separator something that breaks the "statelessness" property we want? Clearly the answer is no. The server doesn't have to remember anything between the two GET requests. There's no concept of a session. Any state that needs to persist between the two GET requests exists only client-side - that's the important distinction. It's completely acceptable - and often required - to have the client persist state between calls to the service.

Unable to access a post's insights for someone else's page

When I access this resource:
https://graph.facebook.com/xxx_yyy/insights
I get this response:
{
"data": [
],
"paging": {
"previous": "https://graph.facebook.com/xxx_yyy/insights?format=json&since=-86400&until=0",
"next": "https://graph.facebook.com/xxx_yyy/insights?format=json&since=0&until=86400"
}
}
The insights data is empty. "xxx_yyy" is a valid post id I got from the feed.
I have the read_insights permission.
I have the offline_access permission.
I'm an admin on the page.
The page has more than 30 likes.
What's causing the API to return an empty insights array?
There are a few requirements for you to get data back from the Facebook Insights graph API call. These don't appear to be clearly documented anywhere, but this is what I have found by trial and error.
The post must be from the page itself, posts from other people won't return insights data
Look at the id in the From object within the post response from facebook, if that is different than the page_id, you won't get metrics.
It's good to note that I haven't unequivocally proved this point, just some anecdotal testing seems to point in this direction
The post must be quite old, I was able to dig up something on one of their Ads FAQs that post insights won't be available for 12-15 hours after the end of the day they were posted on.
"Page post metrics will be available 12 to 15 hours after the end of the day the post was made. Metrics are logged on Pacific Standard Time." Page Post Metrics FAQ -Ads and Business Solutions
I have yet to determine the exact age that posts need to be precisely, but my guess is 36 hours would be a safe general bet. That being said, Facebook Insights data has been known to fall behind from time to time, so I would assume that the timing with which you can attain data will be variable.
FB documentation on page post insights is available primarily in this Facebook blog post
Invalid ID is a key. xxx_yyy in the question means ID must be a combination of appID (xxx part) and postID (yyy part).
So, here is the right Url for post-related metrics:
https://graph.facebook.com/[appID]_[postID]/insights
You must use PAGE token not USER token.
connect to app with manage_pages and read_insights permission
run api https://graph.facebook.com/me/accounts?access_token=USERTOKEN
this expression lists all pages with access token for each page, that you save and use the expression for the post insights
then run expr.
https://graph.facebook.com/xxx_yyy/insights?access_token=PAGETOKEN