| title | GitHub API v3 |
|---|
This describes the resources that make up the official GitHub API v3. If you have any problems or requests please contact support.
- TOC {:toc}
All API access is over HTTPS, and accessed from the api.github.com
domain (or through yourdomain.com/api/v3/ for enterprise). All data is
sent and received as JSON.
$ curl -i https://api.github.com/users/octocat/orgs HTTP/1.1 200 OK Server: nginx Date: Fri, 12 Oct 2012 23:33:14 GMT Content-Type: application/json; charset=utf-8 Connection: keep-alive Status: 200 OK ETag: "a00049ba79152d03380c34652f2cb612" X-RateLimit-Limit: 5000 X-GitHub-Media-Type: github.beta X-RateLimit-Remaining: 4987 Content-Length: 5 Cache-Control: max-age=0, private, must-revalidate X-Content-Type-Options: nosniff []
Blank fields are included as null instead of being omitted.
All timestamps are returned in ISO 8601 format:
YYYY-MM-DDTHH:MM:SSZ
Many API methods take optional parameters. For GET requests, any parameters not specified as a segment in the path can be passed as an HTTP query string parameter:
$ curl -i "https://api.github.com/repos/mojombo/jekyll/issues?state=closed"
In this example, the 'mojombo' and 'jekyll' values are provided for the :owner
and :repo parameters in the path while :state is passed in the query
string.
For POST, PATCH, PUT, and DELETE requests, parameters not included in the URL should be encoded as JSON with a Content-Type of 'application/x-www-form-urlencoded':
$ curl -i -u username -d '{"scopes":["public_repo"]}' https://api.github.com/authorizations
There are three possible types of client errors on API calls that receive request bodies:
-
Sending invalid JSON will result in a
400 Bad Requestresponse.HTTP/1.1 400 Bad Request Content-Length: 35 {"message":"Problems parsing JSON"} -
Sending the wrong type of JSON values will result in a
400 Bad Requestresponse.HTTP/1.1 400 Bad Request Content-Length: 40 {"message":"Body should be a JSON Hash"} -
Sending invalid fields will result in a
422 Unprocessable Entityresponse.HTTP/1.1 422 Unprocessable Entity Content-Length: 149 { "message": "Validation Failed", "errors": [ { "resource": "Issue", "field": "title", "code": "missing_field" } ] }
All error objects have resource and field properties so that your client can tell what the problem is. There's also an error code to let you know what is wrong with the field. These are the possible validation error codes:
missing : This means a resource does not exist.
missing_field : This means a required field on a resource has not been set.
invalid : This means the formatting of a field is invalid. The documentation for that resource should be able to give you more specific information.
already_exists : This means another resource has the same value as this field. This can happen in resources that must have some unique key (such as Label names).
If resources have custom validation errors, they will be documented with the resource.
API v3 uses HTTP redirection where appropriate. Clients should assume that any
request may result in a redirection. Receiving an HTTP redirection is not an
error and clients should follow that redirect. Redirect responses will have a
Location header field which contains the URI of the resource to which the
client should repeat the requests.
301
: Permanent redirection. The URI you used to make the request has been
superseded by the one specified in the Location header field. This and all
future requests to this resource should be directed to the new URI.
302, 307
: Temporary redirection. The request should be repeated verbatim to the URI
specified in the Location header field but clients should continue to use the
original URI for future requests.
Other redirection status codes may be used in accordance with the HTTP 1.1 spec.
Where possible, API v3 strives to use appropriate HTTP verbs for each action.
HEAD : Can be issued against any resource to get just the HTTP header info.
GET : Used for retrieving resources.
POST : Used for creating resources, or performing custom actions (such as merging a pull request).
PATCH
: Used for updating resources with partial JSON data. For instance, an
Issue resource has title and body attributes. A PATCH request may
accept one or more of the attributes to update the resource. PATCH is a
relatively new and uncommon HTTP verb, so resource endpoints also accept
POST requests.
PUT
: Used for replacing resources or collections. For PUT requests
with no body attribute, be sure to set the Content-Length header to zero.
DELETE : Used for deleting resources.
There are three ways to authenticate through GitHub API v3. Requests that require authentication will return 404, instead of 403, in some places. This is to prevent the accidental leakage of private repositories to unauthorized users.
$ curl -u "username" https://api.github.com
$ curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com
$ curl https://api.github.com/?access_token=OAUTH-TOKEN
Read more about OAuth2. Note that OAuth2 tokens can be acquired programmatically, for applications that are not websites.
$ curl https://api.github.com/users/whatever?client_id=xxxx&client_secret=yyyy
This should only be used in server to server scenarios. Don't leak your OAuth application's client secret to your users. Read more about unauthenticated rate limiting.
All resources may have one or more *_url properties linking to other
resources. These are meant to provide explicit URLs so that proper API clients
don't need to construct URLs on their own. It is highly recommended that API
clients use these. Doing so will make future upgrades of the API easier for
developers. All URLs are expected to be proper RFC 6570 URI templates.
You can then expand these templates using something like the uri_template
gem:
>> tmpl = URITemplate.new('/notifications{?since,all,participating}')
>> tmpl.expand
=> "/notifications"
>> tmpl.expand :all => 1
=> "/notifications?all=1"
>> tmpl.expand :all => 1, :participating => 1
=> "/notifications?all=1&participating=1"
Requests that return multiple items will be paginated to 30 items by
default. You can specify further pages with the ?page parameter. For some
resources, you can also set a custom page size up to 100 with the ?per_page parameter.
Note that for technical reasons not all endpoints respect the ?per_page parameter,
see events for example.
$ curl https://api.github.com/user/repos?page=2&per_page=100
The pagination info is included in the Link header. It is important to follow these Link header values instead of constructing your own URLs. In some instances, such as in the Commits API, pagination is based on SHA1 and not on page number.
Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next",
<https://api.github.com/user/repos?page=50&per_page=100>; rel="last"
Linebreak is included for readability.
The possible rel values are:
next
: Shows the URL of the immediate next page of results.
last
: Shows the URL of the last page of results.
first
: Shows the URL of the first page of results.
prev
: Shows the URL of the immediate previous page of results.
We limit requests to 60 per hour for unauthenticated requests. For requests using Basic Authentication or OAuth, we limit requests to 5,000 per hour. You can check the returned HTTP headers of any API request to see your current status:
$ curl -i https://api.github.com/users/whatever HTTP/1.1 200 OK Status: 200 OK X-RateLimit-Limit: 60 X-RateLimit-Remaining: 56
You can also check your rate limit status without incurring an API hit.
GET /rate_limit
<%= headers 200 %> <%= json :rate => {:remaining => 4999, :limit => 5000} %>
If you need to make unauthenticated calls but need to use a higher rate limit associated with your OAuth application, you can send over your client ID and secret in the query string.
$ curl -i https://api.github.com/users/whatever?client_id=xxxxxxxxxxxxxx&client_secret=yyyyyyyyyyyyyyyyyyyyy HTTP/1.1 200 OK Status: 200 OK X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4966
This method should only be used for server-to-server calls. You should never share your client secret with anyone or include it in client-side browser code.
If you are using Basic Authentication or OAuth, and you are exceeding your rate limit, you can likely fix the issue by caching API responses and using conditional requests.
If you're using conditional requests and still exceeding your rate limit, please contact us to request a higher rate limit for your OAuth application.
All API requests MUST include a valid User Agent string. Requests with no User Agent string will be rejected. If you are hitting the API without authentication, we ask that you add some kind of identification to the UA header value. This is so we can contact you if there are problems.
Most responses return Last-Modified and ETag headers. You can use the values
of these headers to make subsequent requests to those resources using the
If-Modified-Since and If-None-Match headers, respectively. If the resource
has not changed, the server will return a 304 Not Modified. Also note: making
a conditional request and receiving a 304 response does not count against your
Rate Limit, so we encourage you to use it whenever possible.
$ curl -i https://api.github.com/user HTTP/1.1 200 OK Cache-Control: private, max-age=60 ETag: "644b5b0155e6404a9cc4bd9d8b1ae730" Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT Status: 200 OK Vary: Accept, Authorization, Cookie X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4996 $ curl -i https://api.github.com/user -H "If-Modified-Since: Thu, 05 Jul 2012 15:31:30 GMT" HTTP/1.1 304 Not Modified Cache-Control: private, max-age=60 Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT Status: 304 Not Modified Vary: Accept, Authorization, Cookie X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4996 $ curl -i https://api.github.com/user -H 'If-None-Match: "644b5b0155e6404a9cc4bd9d8b1ae730"' HTTP/1.1 304 Not Modified Cache-Control: private, max-age=60 ETag: "644b5b0155e6404a9cc4bd9d8b1ae730" Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT Status: 304 Not Modified Vary: Accept, Authorization, Cookie X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4996
The API supports Cross Origin Resource Sharing (CORS) for AJAX requests. you can read the CORS W3C working draft, or this intro from the HTML 5 Security Guide.
Here's a sample request sent from a browser hitting
http://example.com:
$ curl -i https://api.github.com -H "Origin: http://example.com"
HTTP/1.1 302 Found
Any domain that is registered as an OAuth Application is accepted. Here's a sample request for a browser hitting Calendar About Nothing:
$ curl -i https://api.github.com -H "Origin: http://calendaraboutnothing.com"
HTTP/1.1 302 Found
Access-Control-Allow-Origin: http://calendaraboutnothing.com
Access-Control-Expose-Headers: Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes
Access-Control-Allow-Credentials: true
This is what the CORS preflight request looks like:
$ curl -i https://api.github.com -H "Origin: http://calendaraboutnothing.com" -X OPTIONS
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://calendaraboutnothing.com
Access-Control-Allow-Headers: Authorization, X-Requested-With
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE
Access-Control-Expose-Headers: Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-OAuth-Scopes, X-Accepted-OAuth-Scopes
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true
You can send a ?callback parameter to any GET call to have the results
wrapped in a JSON function. This is typically used when browsers want
to embed GitHub content in web pages by getting around cross domain
issues. The response includes the same data output as the regular API,
plus the relevant HTTP Header information.
$ curl https://api.github.com?callback=foo
foo({
"meta": {
"status": 200,
"X-RateLimit-Limit": "5000",
"X-RateLimit-Remaining": "4966",
"Link": [ // pagination headers and other links
["https://api.github.com?page=2", {"rel": "next"}]
]
},
"data": {
// the data
}
})
You can write a JavaScript handler to process the callback like this:
function foo(response) {
var meta = response.meta
var data = response.data
console.log(meta)
console.log(data)
}All of the headers are the same String value as the HTTP Headers with one
notable exception: Link. Link headers are pre-parsed for you and come
through as an array of [url, options] tuples.
A link that looks like this:
Link: <url1>; rel="next", <url2>; rel="foo"; bar="baz"
... will look like this in the Callback output:
<%= json "Link" => [ ["url1", {:rel => "next"}], ["url2", {:rel => "foo", :bar => "baz"}]] %>