up front is dumber • Documentation-driven design • Endpoints, verbs, status codes and examples • Feedback from everyone • Consult and validate during code review, arch review and manual testing • Use Wiki or Markdown because why not? • API != CRUD • Follow use cases, not database tables • Eat your own dog food
links from there • Nice URIs are cute but conceptually treat them as opaque strings • Avoid URI templates • /resource/{resourceId}/subresource/{subresourceId}
process the response • No application specifics here • Choice of generic vs. custom (link) • HAL • JSON-LD • JSON API • Collection+JSON • <your custom media type here>
can be performed against a resource • actors • Represents a user who has performed an action against a resource e.g. owner, manager, assignee • Opt for a generic one if you can • If you have to define your own, make sure you separate it from your domain!
{ „self‟:‟/resources/123‟, „edit‟:‟/resources/123/edit‟ } GET /resources/123/edit 200 OK { „name‟:‟foo‟ } PUT /resources/123/edit { „name‟:‟bar‟ } 204 No Content
and therefore should never change • Headers • Custom request header • X-Api-Version • Custom media type • application/vnd.github.v3+json • Custom media type per resource • application/vnd.github.user.v3+json • Clients need to set the correct headers for every call
clients • Removing or renaming links or resources breaks existing clients • In practice though that doesn‟t happen very frequently • Make breaking changes early on in development so that you don‟t have to make them in production
= new UserBuilder().WithName(“bob”).Persist(); handler = new UserHandler(new SqlLiteRepository(), new Mock<CommandDispatcher>()); }; Because of => { response = handler.Get(user.Id); }; It has_successful_response => response.StatusCode.ShouldEqual(200); It has_user_resource => response.View.Name.ShouldEqual(“bob”); }