This describes the resources that make up the official GitHub API v3. If you have any problems or requests please contact support.

Current Version

By default, all requests receive the v3 version of the API. We encourage you to explicitly request this version via the Accept header.

Accept: application/vnd.github.v3+json


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-GitHub-Media-Type: github.v3
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 1350085394
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:


Summary Representations

When you fetch a list of resources, the response includes a subset of the attributes for that resource. This is the “summary” representation of the resource. (Some attributes are computationally expensive for the API to provide. For performance reasons, the summary representation excludes those attributes. To obtain those attributes, fetch the “detailed” representation.)

Example: When you get a list of repositories, you get the summary representation of each repository. Here, we fetch the list of repositories owned by the octokit organization:

GET /orgs/octokit/repos

Detailed Representations

When you fetch an individual resource, the response typically includes all attributes for that resource. This is the “detailed” representation of the resource. (Note that authorization sometimes influences the amount of detail included in the representation.)

Example: When you get an individual repository, you get the detailed representation of the repository. Here, we fetch the octokit/octokit.rb repository:

GET /repos/octokit/octokit.rb

The documentation provides an example response for each API method. The example response illustrates all attributes that are returned by that method.


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/json’:

$ curl -i -u username -d '{"scopes":["public_repo"]}' https://api.github.com/authorizations

Client Errors

There are three possible types of client errors on API calls that receive request bodies:

  1. Sending invalid JSON will result in a 400 Bad Request response.

     HTTP/1.1 400 Bad Request
     Content-Length: 35
     {"message":"Problems parsing JSON"}
  2. Sending the wrong type of JSON values will result in a 400 Bad Request response.

     HTTP/1.1 400 Bad Request
     Content-Length: 40
     {"message":"Body should be a JSON Hash"}
  3. Sending invalid fields will result in a 422 Unprocessable Entity response.

     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:

Error Name Description
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.

HTTP Redirects

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.

Status Code Description
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.

HTTP Verbs

Where possible, API v3 strives to use appropriate HTTP verbs for each action.

Verb Description
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 Not Found, instead of 403 Forbidden, in some places. This is to prevent the accidental leakage of private repositories to unauthorized users.

Basic Authentication

$ curl -u "username" https://api.github.com

OAuth2 Token (sent in a header)

$ curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com

OAuth2 Token (sent as a parameter)

$ 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.

OAuth2 Key/Secret

$ 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.

Failed login limit

Authenticating with invalid credentials will return 401 Unauthorized:

$ curl -i https://api.github.com -u foo:bar

HTTP/1.1 401 Unauthorized

  "message": "Bad credentials",
  "documentation_url": "https://developer.github.com/v3"

After detecting several requests with invalid credentials within a short period, the API will temporarily reject all authentication attempts for that user (including ones with valid credentials) with 403 Forbidden:

$ curl -i https://api.github.com -u valid_username:valid_password

HTTP/1.1 403 Forbidden

  "message": "Maximum number of login attempts exceeded. Please try again later.",
  "documentation_url": "https://developer.github.com/v3"


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'

Note that page numbering is 1-based and that omitting the ?page parameter will return the first page.

For more information on pagination, check out our guide on Traversing with Pagination.

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:

Name Description
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.

Rate Limiting

For requests using Basic Authentication or OAuth, you can make up to 5,000 requests per hour. For unauthenticated requests, the rate limit allows you to make up to 60 requests per hour. (The Search API has custom rate limit rules.)

You can check the returned HTTP headers of any API request to see your current rate limit status:

$ curl -i https://api.github.com/users/whatever

HTTP/1.1 200 OK
Date: Mon, 01 Jul 2013 17:27:06 GMT
Status: 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 56
X-RateLimit-Reset: 1372700873

The headers tell you everything you need to know about your current rate limit status:

Header Name Description
X-RateLimit-Limit The maximum number of requests that the consumer is permitted to make per hour.
X-RateLimit-Remaining The number of requests remaining in the current rate limit window.
X-RateLimit-Reset The time at which the current rate limit window resets in UTC epoch seconds.

If you need the time in a different format, any modern programming language can get the job done. For example, if you open up the console on your web browser, you can easily get the reset time as a JavaScript Date object.

new Date(1372700873 * 1000)
// => Mon Jul 01 2013 13:47:53 GMT-0400 (EDT)

Once you go over the rate limit you will receive an error response:

HTTP/1.1 403 Forbidden
Date: Tue, 20 Aug 2013 14:50:41 GMT
Status: 403 Forbidden
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1377013266

    "message": "API rate limit exceeded. See https://developer.github.com/v3/#rate-limiting for details."

You can also check your rate limit status without incurring an API hit.

Unauthenticated rate limited requests

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=xxxx&client_secret=yyyy'

HTTP/1.1 200 OK
Date: Mon, 01 Jul 2013 17:27:06 GMT
Status: 200 OK
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4966
X-RateLimit-Reset: 1372700873

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.

Staying within the rate limit

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.

User Agent Required

All API requests MUST include a valid User-Agent header. Requests with no User-Agent header will be rejected. We request that you use your GitHub username, or the name of your application, for the User-Agent header value. This allows us to contact you if there are problems.

Here’s an example:

User-Agent: Awesome-Octocat-App

If you provide an invalid User-Agent header, you will receive a 403 Forbidden response:

$ curl -iH 'User-Agent: ' https://api.github.com/meta
HTTP/1.0 403 Forbidden
Connection: close
Content-Type: text/html

Request forbidden by administrative rules.
Please make sure your request has a User-Agent header.
Check https://developer.github.com for other possible causes.

Conditional requests

Most responses return an ETag header. Many responses also return a Last-Modified header. You can use the values of these headers to make subsequent requests to those resources using the If-None-Match and If-Modified-Since 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
X-RateLimit-Reset: 1372700873

$ 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
X-RateLimit-Reset: 1372700873

$ 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
X-RateLimit-Reset: 1372700873

Cross Origin Resource Sharing

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 Travis CI:

$ curl -i https://api.github.com -H "Origin: http://travis-ci.org"
HTTP/1.1 302 Found
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, 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://travis-ci.org" -X OPTIONS
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE
Access-Control-Expose-Headers: ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true

JSON-P Callbacks

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

  "meta": {
    "status": 200,
    "X-RateLimit-Limit": "5000",
    "X-RateLimit-Remaining": "4966",
    "X-RateLimit-Reset": "1372700873",
    "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. Here’s a minimal example you can try out:

<script type="text/javascript">
function foo(response) {
  var meta = response.meta;
  var data = response.data;

var script = document.createElement('script');
script.src = 'https://api.github.com?callback=foo';


  <p>Open up your browser's console.</p>

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:

  "Link": [
        "rel": "next"
        "rel": "foo",
        "bar": "baz"


Some requests allow for specifying timestamps or generate timestamps with time zone information. We apply the following rules, in order of priority, to determine timezone information for API calls.

Explicitly provide an ISO 8601 timestamp with timezone information

For API calls that allow for a timestamp to be specified, we use that exact timestamp. An example of this is the Commits API.

These timestamps look something like 2014-02-27T15:05:06+01:00. Also see this example for how these timestamps can be specified.

Using the Time-Zone header

It is possible to supply a Time-Zone header which defines a timezone according to the list of names from the Olson database.

$ curl -H "Time-Zone: Europe/Amsterdam" -X POST https://api.github.com/repos/github/linguist/contents/new_file.md

This means that we generate a timestamp for the moment your API call is made in the timezone this header defines. For example, the Contents API generates a git commit for each addition or change and uses the current time as the timestamp. This header will determine the timezone used for generating that current timestamp.

Using the last known timezone for the user

If no Time-Zone header is specified and you make an authenticated call to the API, we use the last known timezone for the authenticated user. The last know timezone is updated whenever you browse the GitHub.com website.


If the steps above don’t result in any information, we use UTC as the timezone to create the git commit.