

18F API Standards - mooreds
https://github.com/18f/api-standards

======
batbomb
I'm not a big fan of reproducing data which probably belongs in headers and
shoving it inside the URL, in case of a request, or the JSON body, in case of
a response. For example: range/offset requests, status codes when there are an
exception, dates or transaction IDs in the request when If-Modified-Since (or
If-Unmodified-Since when doing compare and set) is appropriate.

Also, the underscores for JSON thing isn't really solved. Google's own JSON
style guide recommends camelCase:

[https://google-
styleguide.googlecode.com/svn/trunk/jsoncstyl...](https://google-
styleguide.googlecode.com/svn/trunk/jsoncstyleguide.xml?showone=Property_Name_Format#Property_Name_Format)

~~~
adelevie
Interesting re header data. Could you elaborate as to what kind of data
belongs in headers, and explain why putting this data in headers should be a
bright line requirement or a "sane default"?

~~~
batbomb
First off: Because this functionality is in HTTP spec itself, I believe it
should be leveraged when it makes sense. Otherwise, why even bother with HTTP
and response codes?

Secondly, because you don't need to parse a JSON response to make decisions
based on the response, both clients and servers can potentially be simpler and
faster. If you got a 206 response and 1000 items back, but you made the
request without an accept range header, not knowing if you were going to
receive 10 items or 10000 items, you don't need to parse the JSON to find this
out. This is opposed to just retrieving a 200 response, parsing and processing
1000 items, getting to the end to find a "next" property in your JSON you
weren't expecting, and then firing off another request, when you could have
already queued a second request if you had read the header first before
processing your response. (RFC2616 Section 3.12 gives you some leverage in
specifying range units, so its easy to define the range in items instead of
bytes.)

However, I don't think that creating new headers is a good idea. My
recommendation is simple: If it's in the HTTP spec and you are can use it
according to how it's defined (like my items range example), then you should
use it. If it's not in the spec, just go ahead and put it in the URI/response.
The exceptions to that is maybe custom authentication mechanisms (i.e. HMAC or
cookie based authentication), or anything which may be performance sensitive.
For example, I have endpoints that are used in browser and by batch machines.
It's easy to just use cookies for the browser and HMAC for batch machines.

~~~
tordek
Would you mind expanding a bit on the usage of Range?

The simplest case involving items is clearly `items=10-20`, but that has its
own set of problems (your set must be ordered; I assume you'd use the key
you're sorting over as your `ranges-unit`).

The place where this solution seems less than ideal is when you want to start
from an id, but get a certain number of items. That is, the "infinite scroll"
use case: If you simply do "sort by date, discard 10, return next 10 items",
then you have a race condition where you do your first request, a second agent
adds a new item, and you do your second request: the last item from the
previous page is now the first item from the current page.

So, ideally, I want to request: "Ordered by date, where id > <last-id>, 10
items".

If you're strict about the definitions of `Range`, this doesn't seem possible.

Maybe the best way to do this would be `Range: items=decacfb98eface89+10` or
similar?

~~~
tordek
Additionally, how would you signal "End of List"?

------
adelevie
It's really great to see this on HN. Major kudos should go to Eric Mill, Gray
Brooks, and everyone else who contributed[1] to these standards (as well as
the White House, whose API standards 18F forked[2]). There is a blog post[3]
that further explains 18F's goals for these standards, as well as a bit on how
18F evaluates what becomes a standard and what does not.

These were discussed out in the open, and meaningful feedback, suggestions, or
pull requests are certainly welcome.

[1] [https://github.com/18F/api-
standards/blame/master/README.md](https://github.com/18F/api-
standards/blame/master/README.md)

[2] [https://github.com/WhiteHouse/api-
standards](https://github.com/WhiteHouse/api-standards)

[3] [http://18fblog.tumblr.com/post/91868213233/hot-off-the-
press...](http://18fblog.tumblr.com/post/91868213233/hot-off-the-press-18fs-
api-standards)

------
diafygi
> For clients to be able to use an API from inside web browsers, the API must
> enable CORS.

Great! That means you can build little static apps on github.io that use the
APIs.

Also, would love it if this gave guidance on what style and format of
documentation you need to have for the API.

~~~
adelevie
There is a discussion on documentation in one of the issues[1]. Feel free to
weigh in!

[1] [https://github.com/18F/api-
standards/issues/19](https://github.com/18F/api-standards/issues/19)

------
dpweb
Should the use of GET (when client is sending data) be discontinued
completely? It seems a number of exploits have used data in the URL query
string as part of attacks. Some of Homakov's hijacks come to mind..

Also the fact a URL query string may be more likely to logged who knows where,
at least more likely than a POST body.

------
rayshan
Les Hazlewood's talk on REST API design is one of the best on this topic I've
seen, really got me confident in designing my first API:
[https://www.youtube.com/watch?v=hdSrT4yjS1g](https://www.youtube.com/watch?v=hdSrT4yjS1g)

------
drdaeman
"Just use JSON" means "give up on REST/HATEOAS ideas", right?

~~~
adelevie
If you'd like to elaborate in a way that would be highly visible to 18F, feel
free to weigh in on the issues page[1].

I will point out that JSON is recommended as a default, and if there is a
compelling reason not to use it in a specific case, that should be fine[2].

[1] [https://github.com/18f/api-standards/issues](https://github.com/18f/api-
standards/issues) or [https://github.com/18F/api-
standards/issues/8](https://github.com/18F/api-standards/issues/8)

[2] [https://github.com/18F/api-standards#just-use-
json](https://github.com/18F/api-standards#just-use-json)

