Travis CI API Docs

Hypermedia and discoverability

Version 3 of the Travis CI API does not strictly conform to any one hypermedia specification, but its architecture borrows from Hypermedia As The Engine Of Application State (HATEOAS).

Broadly speaking, this means that:

  • Clients can access the API by first reading the home document at the root of the API, which contains a list of available resources
  • Each resource in the list contains actions, including permitted HTTP verbs, possible resource attributes and URI templates
  • Clients can use these actions to access specific resources
  • Each resource contains metadata that facilitates navigation to related resources

All of this means that, with some knowledge of the way resources are linked, it is possible to build a generic client to navigate the API. Such a client would not require updates in order to handle server side changes.

The API format documentation contains a full list of metadata, but here's a quick example that describes links between resources. Metadata keys start with an @ character.

{
  "@type": "repository",
  "@href": "/repo/1",
  "id":    1,
  "owner": {
    "@type": "organization",
    "@href": "/org/2",
    "id":    2
  }
}

The repository above is accessible via its @href, and the owner of the repository is an organization that also has an @href.

Even without the goal of writing a generic client, the conventions of the API can help clients with resource discovery. Let's take a look at an example.

Imagine we want find out whether or not the most recent build on the default branch of our repository passed. We will need to:

  1. Work out how to request repository data
  2. Find out the default branch of the repository
  3. Find out the last build on that branch

Note that the following requests do not contain authentication headers, and some responses are abbreviated for clarity.

First, we read the home document to find out which resources the API provides.

curl -H "Travis-API-Version: 3" https://api.travis-ci.com/
{
  "@type":     "home",
  "@href":     "/",
  "resources": {
    "repository": {
      "@type":    "resource",
      "actions":  {
        "find":   [
          {
            "@type":          "template",
            "request_method": "GET",
            "uri_template":   "/repo/{repository.id}{?include}"
          },
          {
            "@type":          "template",
            "request_method": "GET",
            "uri_template":   "/repo/{repository.slug}{?include}"
          }
        ]
      }
    }
  }
}

The response contains a resource named repository which has a find action. This action has two templates which inform clients how to make a GET request, replacing part of the URI with either the ID or the slug of the repository. The templates also contain an optional include parameter, which is not covered in eager loading.

We don't know the ID of the repository, but we do know its slug from the URLs on Travis CI and GitHub: travis-ci/travis-web. This is enough to request more data about the repository.

When passing a slug to the API you always need to encode it, so we replace the / in travis-ci/travis-web with %2F.

curl -H "Travis-API-Version: 3" \
     -H "Authorization: token xxxxxxxxx" \
    https://api.travis-ci.com/repo/travis-ci%2Ftravis-web

The response contains information about the repository, including a default_branch key:

{
  "@type":           "repository",
  "@href":           "/repo/269284",
  "@representation": "standard",
  "id":              269284,
  "name":            "travis-web",
  "slug":            "travis-ci/travis-web",
  "description":     "The Ember web client for Travis CI",
  "owner":           {
    "@type":         "organization",
    "id":            87,
    "login":         "travis-ci",
    "@href":         "/org/87"
  },
  "default_branch":  {
    "@type":           "branch",
    "@href":           "/repo/269284/branch/master",
    "@representation": "minimal",
    "name":            "master"
  }
}

Nested resources have a minimal representation (see @representation). This avoids circular nesting in the JSON responses – imagine a repository that contains an owner, which in turn contains a list of repositories, and so on. It also reduces load on our database. In any case, the minimal representation of the nested resource always contains enough information for the client to make a more detailed request if necessary.

As the default_branch has a @type of branch, clients could refer back to the home document to determine which actions are available for a branch. But since we made a GET request for the repository, we can be sure that any nested resources are also available via GET, so we navigate to the @href of the default branch.

curl -H "Travis-API-Version: 3" \
     -H "Authorization: token xxxxxxxxxx" \
    https://api.travis-ci.com/repo/269284/branch/master

In the response you can see what the the most recent build (last_buid) is, and what state it is in ("passed").

{
  "@type":            "branch",
  "@href":            "/repo/269284/branch/master",
  "@representation":  "standard",
  "name":             "master",
  "repository":       {
    "@type":           "repository",
    "@href":           "/repo/269284",
    "@representation": "minimal",
    "id":              269284,
    "name":            "travis-web",
    "slug":            "travis-ci/travis-web"
  },
  "default_branch":   true,
  "exists_on_github": true,
  "last_build":       {
    "@type":               "build",
    "@href":               "/build/208714092",
    "@representation":     "minimal",
    "id":                  208714092,
    "number":              "7631",
    "state":               "passed",
    "duration":            1162,
    "event_type":          "push",
    "previous_state":      "passed",
    "pull_request_title":  null,
    "pull_request_number": null,
    "started_at":          "2017-03-07T19:35:50Z",
    "finished_at":         "2017-03-07T19:40:56Z"
  }
}

To get more information about the jobs inside that build, keep following the @href links.

If you'd like to try this out right away, see the API explorer.