Revisions

Resource revisions are immutable resources which capture the revision history of a resource. It is analogous to the chain of Git commits in source code control: you cannot change the revision of a document that was committed in the past.

Resource revisions also support event sourcing where a full audit history of a resource can be traced and inspected. Many types of resources can support revisions, so this is a general pattern.

To explain revisions, we will use the Products API and discuss how product revisions are made.

Each product has a URI:

http://api.thirdpatybank.com/products/{productId}

Corresponding to each product is a collection of revisions (using the collections pattern):

http://api.thirdpatybank.com/products/{productId}/revisions

and within the revisions collection are specific revision instances, identified with a unique revisionId:

http://api.thirdpatybank.com/products/{productId}/revisions/{revisionId}

Creating a new resource such as a new product will create a new product instance (we use 123 as the {productId} in this example, although it will actually be a GUID) and implicitly create a revision. The Location and Content-Location response headers from the POST will refer to the same resource and data, but with two URLs. The two URLs refer to the exact same resource. The new product is at URI /products/123 but at this point in time, that is an alias for the first (and only) revision, /products/123/revisions/2018-05-11T09:00:00Z . Doing a GET on either has the same effect and returns the same representation of product 123.

The effectiveStartAt timestamp indicates when this resource was created and when the specific revision was created. Since this is the current (active) revision, the effectiveEndAt is not set:

A Product with one revision

A POST to the resource’s revisions sub-collection creates a new revision, setting the effectiveEndAt of the previous revision and the effectiveStartAt of the new current revision to the timestamp of the update. The Location response header will refer to the resource location without the revision path (such as /products/123 ) and the Content-Location response header will refer to the most recent revision /products/123/revisions/2018-05-20T10:00:00Z , and within the _links in each product instance, prev points to the previous revision (if it exists) and next points to the next revision (if it exists). These links refer to chronologically previous/next revisions.

Creating a second product revision

A GET on either the product by ID or the product by revision will return the Content and the Content-Location response headers.

GET .../revisions on the revisions collection returns a paginated, filterable collection of the revisions of the specific resource; the default is reverse chronological time.

  • http://api.thirdpatybank.com/products/123/revisions/2018-05-20T10:00:00Z
  • http://api.thirdpatybank.com/products/123/revisions/2018-05-11T09:00:00Z

Revisions as resources allows linking to specific revisions of mutable resources: if an account is created using a specific product, the account can link to the product revision that was active at that time. Performing a GET on the default resource (for example GET /products/123 ) will return the Content-Location header of the most recent specific revision: /products/123/revisions/2018-05-11T09:00:00Z and the account can always identify the state of the product that was effective when the account was created, since that revision is immutable.

The chain of revisions, from most recent to first revision, provides the history of the resource.