Continuous Integration — entry 005 of 5
Travis CI
Travis CI's REST API reads and manages builds, repositories, branches, and jobs, and its docs specify a token-based Authorization: token "<token>" header rather than an OAuth redirect flow, reconfirming the stored API Key auth model. A live GET against api.travis-ci.com returned a structured JSON response (not a raw connection error), and the same request sent with an Origin header carried access-control-allow-origin: * on both the GET and its OPTIONS preflight, resolving the previously unknown CORS support to open. Travis CI's own pricing page still lists an "Open Source Only" free tier alongside paid Linux/FreeBSD plans, so it remains freemium rather than fully paid.
Travis CI's v3 API reads and manages builds, repositories, branches, and jobs over a hypermedia JSON format, where every object carries @type and @href fields pointing back into the API. A live GET this run against a public GitHub repo's build list returned real build history with no token, no signup, and no Authorization header of any kind.
GreatAPIs Score
Auth quickstart
- Public-repo reads need no key at all — a live GET this run against
/repo/travis-ci%2Ftravis-web/builds?limit=1with just theTravis-API-Version: 3header returned real build data withaccess-control-allow-origin: *, noAuthorizationheader present. - Writes, and reads against a private repository, do need the stored
API Keyauth: get a token viatravis login --pro(or the GitHub OAuth exchange at/auth/github) and send it asAuthorization: token "<token>". A live GET this run against a repo slug that doesn't exist returned the exact same404 repository not found (or insufficient access)message a real private repo would give an unauthenticated caller — the API deliberately doesn't distinguish the two, so a bare 404 here never confirms whether a repo exists.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
List the most recent build for a public repository
GEThttps://api.travis-ci.com/repo/travis-ci%2Ftravis-web/builds?limit=1
Travis-API-Version: 3
{"@type":"builds","@href":"/repo/travis-ci%2Ftravis-web/builds?limit=1","@pagination":{"limit":1,"offset":0,"count":24096,"is_first":true,"is_last":false,"next":{"@href":"/repo/travis-ci%2Ftravis-web/builds?limit=1&offset=1"}},"builds":[{"@type":"build","@href":"/build/278462667","id":278462667,"number":"28769","state":"errored","duration":626,"event_type":"cron","started_at":"2026-07-09T20:19:10Z","finished_at":"2026-07-09T20:24:06Z","private":false,"repository":{"@type":"repository","@href":"/repo/4375425","id":4375425,"name":"travis-web","slug":"travis-ci/travis-web"},"branch":{"name":"master"},"commit":{"sha":"6fc98e92be2fc377343f20122d9973e4e4d93295","message":"Merge pull request #3036 from travis-ci/Release_260204"},"jobs":[{"id":640002777},{"id":640002778},{"id":640002779}]}]}Trimmed for length — the live response also carries @representation, @permissions, tag, stages, and created_by on the build, and first/last/prev cursor links alongside next in @pagination. count (24,096) is the repo's entire build history, not the size of this page; next.@href is a ready-to-fetch relative path, not a bare offset token.
Developer reference
Gotchas & limits
- The repo slug must be URL-encoded (
%2Ffor the slash) — a live GET this run with a literal slash (/repo/travis-ci/travis-web/builds) returned a404with{"@type":"error","error_type":"not_found","error_message":"resource not found (or insufficient access)"}, not the build list. Travis-API-Version: 3is required on every request — a live GET this run without it returned a bare404 {"file":"not found"}from what looks like a legacy static-file router, with none of the v3 hypermedia envelope.travis-ci.orgis retired — a live GET this run against the old.orghost returned404with an empty{}body and no@typeenvelope at all.api.travis-ci.comis the only live host now, for both open-source and private repos.- Every object is wrapped in a hypermedia envelope (
@type,@href, and often@representation/@permissions) — plan to unwrap one extra layer versus a typical flat REST response. - A nonexistent repo and a private repo you can't access return the identical
404 {"error_type":"not_found","error_message":"repository not found (or insufficient access)"}— confirmed live this run against a made-up slug — so this endpoint alone can't tell you which case you're in.