API Documentation Guidelines
Properly documenting an API's end points is just as important as writing the code that builds it. Documentation is generally stored in the README.md
file in at the base of your repo, and is written using Markdown formatting. You can get a feel for the formatting used by viewing any README.md
file as raw (click the "Raw" button in GitHub)—including this one. Good documentation:
- Helps the engineer as they build the API. Writing documentation, before writing any code, provides a chance to think about things like data structure and validation requirements outside the context of implementation. Once these basic details have been established, they provide a great map for what will be built. Will it always be perfect the first time? Absolutely not, but thinking about things even just a little bit before diving in reduces the likelihood of major changes being necessary at a later date. Also, this doesn't mean that the entire API needs to be drafted out in the
README
prior to development. Taking it one end point at a time is fine as well. - Helps the engineers tasked with consuming the API get their job done. Documentation is the first line of defense for answering questions. It can do the talking so you don't have to be interrupted. Like before, nothing is perfect the first time and questions will arise, but they will be far fewer than with no documentation at all. Help a coder out.
Formatting
The following examples serve to illustrate a pattern for formatting documentation for a CRUD endpoint.
- Begin with the method name—
GET
,POST
,PUT
,PATCH
, orDELETE
—followed by the endpoint's URL. - For endpoints that accept input via a JSON-formatted request body, show an example in a Body section, followed by a Notes section with specifics about data formats.
GET
endpoints that accept optional query parameters can skip the Body and list them in the Notes section.
- The Response section should show a sample of a valid JSON response body.
- Finally, list the possible Status Codes, especially paying attention to
4xx
codes and their meaning.
Add a new building
POST: /api/building
Body:
{
"name": "Super Cool Building",
"latitude": 41.893740,
"longitude": -87.635330
}
Notes:
name
: the name of the building (string)latitude
: GPS coordinates, between-90.0 - 90.0
(float)longitude
: GPS coordinates, between-180.0 - 180.0
(float)
Response:
{
"id": "7032AC0B-BE6D-4873-81B7-7BFD91BFD5F0",
"name": "Super Cool Building",
"latitude": 41.893740,
"longitude": -87.635330
}
Status Codes:
201
if successfully created400
if incorrect data is provided409
if a building with this name already exists
Get a list of buildings
GET: /api/building
Notes:
An optional latitude and longitude can be supplied as query parameters to narrow the results within a two mile radius.
latitude
: GPS coordinates, between-90.0 - 90.0
(float)longitude
: GPS coordinates, between-180.0 - 180.0
(float)
Response:
{
"count": 24,
"next": "http://blahblahblah.com/api/building?page=2",
"previous": null,
"results": [
{
"id": "7032AC0B-BE6D-4873-81B7-7BFD91BFD5F0",
"name": "Super Cool Building",
"latitude": 41.893740,
"longitude": -87.635330
},
...
]
}
Status Codes:
200
if successful
Get a single building
GET: /api/building/:id
Response:
{
"id": "7032AC0B-BE6D-4873-81B7-7BFD91BFD5F0",
"name": "Super Cool Building",
"latitude": 41.893740,
"longitude": -87.635330
}
Status Codes:
200
if successful404
if building does not exist
Update a building
PATCH: /api/building/:id
Body:
{
"name": "New Building Name",
"latitude": 51.5033630,
"longitude": -0.1276250
}
Notes:
name
: the name of the building (string)latitude
: GPS coordinates, between-90.0 - 90.0
(float)longitude
: GPS coordinates, between-180.0 - 180.0
(float)
Response:
{
"id": "7032AC0B-BE6D-4873-81B7-7BFD91BFD5F0",
"name": "New Building Name",
"latitude": 51.5033630,
"longitude": -0.1276250
}
Status Codes:
200
if successful400
if incorrect data is provided404
if building does not exist409
if a building with this name already exists
Delete a building
DELETE: /api/building/:id
Response: None
Status Codes:
204
if successful404
if building does not exist
Bitmasks
Option sets that are expected to contain more than ~3 items can be stored and transported more efficiently using a bitmask. Keep to these standards to avoid any ambiguity about bit order. Specify when a bit becomes unused. Use no more than 32 bits.
For Example:
Starting from the least significant bit these flags are available:
0
: Email when Invite Accepted (defaultOFF
)1
: Email when Invite Rejected (defaultOFF
)2
: Email when Cubs Win (defaultON
)3
: UNUSED4
: SMS when Dinner is Ready (defaultON
)Default settings:
20
(10100
with least significant bit on right)
DateTimes
All datetimes sent and received by the API should conform to RFC 3339 Internet timestamp standard. For example: 2015-04-16T13:34:22.023000Z
.
In Python use the formatting string '%Y-%m-%dT%H:%M:%S.%fZ'
. Go can use time.RFC3339
. Enforcing the setting in Django Rest Framework is detailed in the DRF standards doc.