GithubHelp home page GithubHelp logo

api-standards's Introduction

White House Web API Standards

Guidelines

This document provides guidelines and examples for White House Web APIs, encouraging consistency, maintainability, and best practices across applications. White House APIs aim to balance a truly RESTful API interface with a positive developer experience (DX).

This document borrows heavily from:

Pragmatic REST

These guidelines aim to support a truly RESTful API. Here are a few exceptions:

RESTful URLs

General guidelines for RESTful URLs

  • A URL identifies a resource.
  • URLs should include nouns, not verbs.
  • Use plural nouns only for consistency (no singular nouns).
  • Use HTTP verbs (GET, POST, PUT, DELETE) to operate on the collections and elements.
  • You shouldn’t need to go deeper than resource/identifier/resource.
  • Put the version number at the base of your URL, for example http://example.com/v1/path/to/resource.
  • URL v. header:
    • If it changes the logic you write to handle the response, put it in the URL.
    • If it doesn’t change the logic for each response, like OAuth info, put it in the header.
  • Specify optional fields in a comma separated list.
  • Formats should be in the form of api/v2/resource/{id}.json

Good URL examples

Bad URL examples

HTTP Verbs

HTTP verbs, or methods, should be used in compliance with their definitions under the HTTP/1.1 standard. The action taken on the representation will be contextual to the media type being worked on and its current state. Here's an example of how HTTP verbs map to create, read, update, delete operations in a particular context:

HTTP METHOD POST GET PUT DELETE
CRUD OP CREATE READ UPDATE DELETE
/dogs Create new dogs List dogs Bulk update Delete all dogs
/dogs/1234 Error Show Bo If exists, update Bo; If not, error Delete Bo

(Example from Web API Design, by Brian Mulloy, Apigee.)

Responses

  • No values in keys
  • No internal-specific names (e.g. "node" and "taxonomy term")
  • Metadata should only contain direct properties of the response set, not properties of the members of the response set

Good examples

No values in keys:

"tags": [
  {"id": "125", "name": "Environment"},
  {"id": "834", "name": "Water Quality"}
],

Bad examples

Values in keys:

"tags": [
  {"125": "Environment"},
  {"834": "Water Quality"}
],

Error handling

Error responses should include a common HTTP status code, message for the developer, message for the end-user (when appropriate), internal error code (corresponding to some specific internally determined ID), links where developers can find more info. For example:

{
  "status" : 400,
  "developerMessage" : "Verbose, plain language description of the problem. Provide developers
   suggestions about how to solve their problems here",
  "userMessage" : "This is a message that can be passed along to end-users, if needed.",
  "errorCode" : "444444",
  "moreInfo" : "http://www.example.gov/developer/path/to/help/for/444444,
   http://drupal.org/node/444444",
}

Use three simple, common response codes indicating (1) success, (2) failure due to client-side problem, (3) failure due to server-side problem:

  • 200 - OK
  • 400 - Bad Request
  • 500 - Internal Server Error

Versions

  • Never release an API without a version number.
  • Versions should be integers, not decimal numbers, prefixed with ‘v’. For example:
    • Good: v1, v2, v3
    • Bad: v-1.1, v1.2, 1.3
  • Maintain APIs at least one version back.

Record limits

  • If no limit is specified, return results with a default limit.
  • To get records 51 through 75 do this:

Information about record limits and total available count should also be included in the response. Example:

{
    "metadata": {
        "resultset": {
            "count": 227,
            "offset": 25,
            "limit": 25
        }
    },
    "results": []
}

Request & Response Examples

API Resources

GET /magazines

Example: http://example.gov/api/v1/magazines.json

Response body:

{
    "metadata": {
        "resultset": {
            "count": 123,
            "offset": 0,
            "limit": 10
        }
    },
    "results": [
        {
            "id": "1234",
            "type": "magazine",
            "title": "Public Water Systems",
            "tags": [
                {"id": "125", "name": "Environment"},
                {"id": "834", "name": "Water Quality"}
            ],
            "created": "1231621302"
        },
        {
            "id": 2351,
            "type": "magazine",
            "title": "Public Schools",
            "tags": [
                {"id": "125", "name": "Elementary"},
                {"id": "834", "name": "Charter Schools"}
            ],
            "created": "126251302"
        }
        {
            "id": 2351,
            "type": "magazine",
            "title": "Public Schools",
            "tags": [
                {"id": "125", "name": "Pre-school"},
            ],
            "created": "126251302"
        }
    ]
}

GET /magazines/[id]

Example: http://example.gov/api/v1/magazines/[id].json

Response body:

{
    "id": "1234",
    "type": "magazine",
    "title": "Public Water Systems",
    "tags": [
        {"id": "125", "name": "Environment"},
        {"id": "834", "name": "Water Quality"}
    ],
    "created": "1231621302"
}

POST /magazines/[id]/articles

Example: Create – POST http://example.gov/api/v1/magazines/[id]/articles

Request body:

[
    {
        "title": "Raising Revenue",
        "author_first_name": "Jane",
        "author_last_name": "Smith",
        "author_email": "[email protected]",
        "year": "2012",
        "month": "August",
        "day": "18",
        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eget ante ut augue scelerisque ornare. Aliquam tempus rhoncus quam vel luctus. Sed scelerisque fermentum fringilla. Suspendisse tincidunt nisl a metus feugiat vitae vestibulum enim vulputate. Quisque vehicula dictum elit, vitae cursus libero auctor sed. Vestibulum fermentum elementum nunc. Proin aliquam erat in turpis vehicula sit amet tristique lorem blandit. Nam augue est, bibendum et ultrices non, interdum in est. Quisque gravida orci lobortis... "
    }
]

Mock Responses

It is suggested that each resource accept a 'mock' parameter on the testing server. Passing this parameter should return a mock data response (bypassing the backend).

Implementing this feature early in development ensures that the API will exhibit consistent behavior, supporting a test driven development methodology.

Note: If the mock parameter is included in a request to the production environment, an error should be raised.

JSONP

JSONP is easiest explained with an example. Here's one from StackOverflow:

Say you're on domain abc.com, and you want to make a request to domain xyz.com. To do so, you need to cross domain boundaries, a no-no in most of browserland.

The one item that bypasses this limitation is <script> tags. When you use a script tag, the domain limitation is ignored, but under normal circumstances, you can't really DO anything with the results, the script just gets evaluated.

Enter JSONP. When you make your request to a server that is JSONP enabled, you pass a special parameter that tells the server a little bit about your page. That way, the server is able to nicely wrap up its response in a way that your page can handle.

For example, say the server expects a parameter called "callback" to enable its JSONP capabilities. Then your request would look like:

    http://www.xyz.com/sample.aspx?callback=mycallback

Without JSONP, this might return some basic javascript object, like so:

    { foo: 'bar' }

However, with JSONP, when the server receives the "callback" parameter, it wraps up the result a little differently, returning something like this:

    mycallback({ foo: 'bar' });

As you can see, it will now invoke the method you specified. So, in your page, you define the callback function:

    mycallback = function(data){
        alert(data.foo);
    };

http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about?answertab=votes#tab-top

api-standards's People

Contributors

benforeva avatar carloseberhardt avatar gplocke avatar jabley avatar jrep avatar noahkunin avatar pborreli avatar philipashlock avatar traviscarden avatar wardi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api-standards's Issues

Thanks and FYI

Hi @WhiteHouse.

18F published its initial API Standards, a process that began with forking your great work. Thank you very much for your leadership in this area and let us know if you want us to submit the individual sections as pull requests for conversation here.

Consider using the IETF API-Problem specification for error messages

Referring to the https://github.com/WhiteHouse/api-standards#error-handling section, it is great that the WH API standards promote helpful error messages for developers who consume the APIs. Have you considered adopting the IETF API-Problem specification? It appears to be similar in goals to what WH is trying to do, but it might be good to adopt a standard response format. There is a relevant blog post at http://www.mnot.net/blog/2013/05/15/http_problem, and there is some PHP tooling around the spec at https://github.com/Crell/ApiProblem.

Thanks!
Chris

POST response format and behavior is not specified

The URL examples show that the GET response format is specified with a file extension like .json or .xml, but no extension is shown for the POST example and there's no explanation of the behavior of a successful POST response. I would suggest that the format for POST responses is specified the same way as GET responses so that an error message or a success message will be returned with the desired format.

Note that specifying this response format could be completely independent from the format of the actual payload sent in the POST request. That's not specified here anywhere either, but I'll note that as a separate issue.

Clarify how JSONP URLs are constructed

The example of JSONP usage doesn't include a file format extension in the URL. Should this extension be .json or .jsonp? I would recommend .jsonp since it effectively behaves like a different format

CORS?

This is just my personal opinion so please feel free to take with a grain of salt, but I have found many API designers share it, so for whatever it's worth:

You may not need JSONP if you enable CORS Access-Control-Allow-Origin: * (http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) in all your API responses.

Enabling it does not decrease the security of your API wee bit (many would argue JSONP is less secure) and removes a lot of complexity.

Email confirmation RESTful api

I'm trying to create a new endpoint for confirming email after registering new user but I doubt if it's right or not?
Here is what I have in my mind :

/users/{id}/confirmations/{token}

  • "confirmation" or "confirmations" ?
  • When the endpoint is a resource? is "confirmation" a resource?

Additional common/important HTTP Response Codes

200 OK: Success!

201 Created: a common return code for a successful HTTP POST (or PUT in idempotent creations)

202 Accepted: request was accepted, but has not fully been processed, yet. A common code to return for asynchronous calls.

304 Not Modified: There was no new data to return (think: cache). <-- This is very important!

400 Bad Request: Invalid Request. Error message will be returned to provide further details.

401 Unauthorized: Authentication credentials were missing or incorrect.

403 Forbidden: Valid request that was refused. Attempt to access a resource that the client does not have permission to. Error message will be returned to provide further details.

404 Not Found: The URL requested is invalid or the resource requested, such as a document or a user, does not exists.

406 Not Acceptable: Returned when parameters passed are correct in theory and individually, but when combined can not be satisfied because the combination makes no sense (e.g. cart_id from one user is used with a user_id from another user). If possible, an error message will be returned to provide further details.

500 Internal Server Error: Something went horribly wrong and we were not smart enough to provide more details :) Hopefully a very rare response code.

503 Service Unavailable: Servers are offline for maintenance or went down under load (oops).

A few CDC Enhancements

At CDC we have been working developers at HHS and codeveloping our new API with this specification on our Content Services project. We have two suggested enhancements.

  1. Allowing for multiple message returns in the JSON return set to provide independent information for bulk actions and where possible deeper information to the caller.
    "status":200,"message":[],
  2. Move the pagination information into a separate structure to better delineate it and provide more navigation information.

pagination":{"count":3384,
"offset":0,
"page":1,
"max":2,
"totalPages":1692,
"sort":"datepublished Desc",
"currentUri":"http://prototype.cdc.gov/api/v1/resources/media/?max=2",
"previousUri":null,
"nextUri":"http://prototype.cdc.gov/api/v1/resources/media/?max=2&page=2&rsid=e5f13d08-fd94-413e-ae0e-9112c5c88415"}
}

This is not "Truly Restful"

I would drop "truly RESTful API" mentioned couple times. Especially since you mention Roy's name in the same document. I don't want to speak for Roy, but considering his writing he would not call these guidelines RESTful at all. Case in point:
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

Your document adheres to what a lot of people commonly call REST and what I used to call "pragmatic REST" years ago, but it's not Hypermedia APIs, which is what Roy would call "true REST".

Add rationale to some guidelines.

I have found this a great resource when defining REST APIs. One small thing.

In the responses section, it is stated that "No values in keys". Whilst I agree with this, and get some way in being able to clearly articulate why, it would be good to ensure that the rationale behind the standard is captured and documented.

Version in Accept Header rather than URL

Generally, it's better practice to put the version of the service in the HTTP Accept Header. The URL should uniquely identify the identities, independent of the representation of those entities on the wire. The version of the schema should be seen as a representation of the entities.

Clarify file formats and use of Content-Type headers

The use of format terms like "XML" and "JSON" can be ambiguous without specifying HTTP Content-Type headers. I would also recommend specifying the character encoding here, but I'll mention that as another issue. I would recommend XML and JSON usage as the following types and the guidelines should articulate that HTTP headers should match this for each format.

XML: Content-Type: text/xml; charset=utf-8
JSON: Content-Type: application/json; charset=utf-8

JSON design patterns

JSON design patterns - JSON is awesome because it's free form, but there are certain design patterns (e.g., having URLs to all the related resources -- see e.g., GitHub's API which does this really well), and returning either an object (single record) or an array of objects (multiple records).

Recommend encoding type

I would suggest UTF-8 and this should be specified in the HTTP Content-Type header as well, eg for json the full header would be

Content-Type: application/json; charset=utf-8

See http://utf8everywhere.org/ for some arguments for UTF-8 and arguments against other encodings like UTF-16

Recommend how capitalization is handled

URLs, XML, and JSON are all case sensitive. In many programing languages like javascript camel case is preferred for variable names, but API resources specified in a URL are often preferred to be all lowercase and hyphen separated, while the names of values in json are often lowercase and underscore separated. This seems to be the implied convention based on the examples shown and matches my own personal preference, but this should be clarified. Camel case seems appropriate as code, but not as data.

JSONP

json-p is being replaced by CORS because of security issues. Please remove this section or at least mention this fact.

P.S. Thanks for this awesome page :)

Some questions on the directory structure

Hello, We're trying to finalize the API directory structure here at the U.S. Patent and Trademark Office--based on your examples--and have some questions on the examples. So that we're sure we're understanding them correctly, any chance you have time for questions? Thanks, Arva

JSONP, Access Control Allow Origin

Would be cool to give JSONP and Access Control Allow Origin a shout out (unless I missed it?). As a frequent consumer of government APIs, not being able to do things client side is a huge barrier to quick, cool projects.

Accept-type headers

Accept-type headers - In addition to appending .json, I should also be able to send accept-type "application/json". Makes working with Backbone and other client-side libraries a lot easier.

POST request payload, format, and behavior are not clearly specified

It's not clear if the example of json data for POST /magazines/[id]/articles is the payload sent as the POST request or if its the response from a successful POST request, or both. Typical POST requests with an HTML webform are sent as application/x-www-form-urlencoded and that is specified in the header. I'm guessing the example shown is sent as json, but that should be clarified. If these guidelines are agnostic about how POST requests are made in the same way they're agnostic about xml or json responses, then perhaps it should discuss how people can know the options available. Perhaps specifying the format as an extension in the URL is used not only to indicate the response format, but also the payload being sent in the request.

POST is not always "create" and PUT is not always "update".

This is somewhat minor, but the document says that HTTP POST is a "Create". That is not correct. There is no one-to-one mapping between CRUD and HTTP verbs. It boils down to whether the operation is idempotent or not.

HTTP POST is non-idempotent, HTTP PUT is idempotent.

As for CRUD: Create can be both idempotent (if you provide ID of the record that ought to be created, e.g. you are creating a user with specific user_id) or non-idempotent (if you provide data but not the ID). So there're many cases where PUT is absolutely fine for a Create operation.

Furthermore, many services do not support anything but GETor POST. This is because browsers do not support any other verb so lots of proxies and most CDNs also only implement GET and POST with zero support for anything else. We have had some conversations with major CDN providers to address this very issue and I know some of them are actively working on it. Point is: a lot of pragmatic APIs implement POST for "delete" and "update" with so-called Method Override.

Speaking of which, this document could probably use a word or two about method overrides.

Mention this as a nice-to-have

  • Related - a mention to the genearl design pattern that if I have a resource (e..g, a blog post), I should just be able to add .json to the same URL and get it in the format I want (or .xml, etc.) Each resource has a URL, regardless of format be it human readable or machine readable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.