Reader API

Access Readability's features including queueing articles, retrieving reading lists, favoriting, and many more.
samson@readability:~/developers/api/reader
#

Authentication

All requests to the Readability service require access tokens. You can acquire an access token two ways:

  1. OAuth: API Keys + User Authorization via Callbacks—Recommended for Web Apps
  2. XAuth: API Keys + Username & Password—Recommended for Native Apps

OAuth Endpoints:

  • https://www.readability.com/api/rest/v1/oauth/authorize/
  • https://www.readability.com/api/rest/v1/oauth/request_token/
  • https://www.readability.com/api/rest/v1/oauth/access_token/

XAuth requires a single endpoint for authorization:

  • https://www.readability.com/api/rest/v1/oauth/access_token/

XAuth functions just like OAuth, except it skips the authorization process. Along with the standard oauth_* signing keys, the client sends x_auth_username, x_auth_password, and x_auth_mode (set to client_auth). The response is an authorized access token. In most cases, you should do your best to support OAuth proper. This allows users to never have to pass their Readability username and password into your (third-party) application, making your application, and our application, more secure. If you are using XAuth, do not store the user's password. Use it once to retrieve an access token and discard it.

Quick Start

The most obvious use case for the Readability API is to be able to add a bookmark into a user's queue. Here's how it's done:

Request

POST /api/rest/v1/bookmarks
Content-Type: application/x-www-form-urlencoded

url=http://blog.arc90.com/2010/11/30/silence-is-golden/&favorite=1

Response

HTTP/1.0 202 Accepted
Location: /api/rest/v1/bookmarks/119
X-Article-Location: /api/rest/v1/articles/xj28dwkx

You can browse to the new bookmark at the URI returned in the Location header:

Request

GET /api/rest/v1/bookmarks/119 HTTP/1.1

Response

HTTP/1.1 200 OK
Date: Thu, 12 Oct 2010 20:13:58 GMT
Last-Modified: Wed, 12 Oct 2010 12:39:02 -0500
Content-Type: application/json

{
    "user_id": 1,
    "read_percent": "0.0",
    "date_updated": "2010-10-12 13:38:33",
    "favorite": true,
    "article": {
        "domain": "blog.arc90.com",
        "title": "Silence is Golden",
        "url": "http://blog.arc90.com/2010/11/30/silence-is-golden/",
        "lead_image_url": null,
        "author": "Tim Meaney",
        "excerpt": "I’ve been building software for 15 years and continue to be…",
        "direction": "ltr",
        "word_count": 1094,
        "date_published": "2010-11-30 00:00:00",
        "dek": null,
        "processed": true,
        "id": "tg8if9uj"
    },
    "id": 119,
    "date_archived": null,
    "date_opened": null,
    "date_added": "2010-10-12 13:38:33",
    "article_href": "/api/rest/v1/articles/tg8if9uj",
    "date_favorited": "2010-10-12 13:38:33",
    "archive": false
}

API Libraries

There's a growing list of API Libraries available for integration in your project:

Python
readability-api by The Readability Team. - MIT License - Source on GitHub.
Ruby (Rails)
Readability for Rails by Luke van der Hoeven - MIT License
Ruby
ReadIt by Dongbin Li

If you've written a wrapper for the Readability API, tell us about it.

Data Formats

All requests are, by default, provided as JSON. You may also pass ?format=xml in the URL to convert this into XML data to be consumed.

API data is encoded in UTF-8. You may need to convert UTF-8 for characters to appear properly.

Resources, Representations & Errors

Resources

/

Methods

GET

Retrieve the base API URI - information about subresources.

available response representations:

/articles/{article_id}

Methods

GET

Retrieve a single Article, including its content. Accessible by any authenticated user.

available response representations:

potential faults:

/bookmarks?archive&favorite&domain&added_since&added_until&opened_since&opened_until&archived_since&archived_until&favorited_since&favorited_until&updated_since&updated_until&order&page&per_page&exclude_accessibility&only_deleted&tags

Methods

GET

Retrieve the bookmarks collection. Automatically filtered to the current user.
request query parameters
parametervaluedescription

archive

integer

One of:

  • 0
  • 1
Filter bookmarks by archived status.

favorite

integer

One of:

  • 0
  • 1
Filter bookmarks by favorited status.

domain

string

Filter bookmarks by domain.

added_since

dateTime

Filter bookmarks by date added (since this date).

added_until

dateTime

Filter bookmarks by date added (until this date).

opened_since

dateTime

Filter bookmarks by date opened (since this date).

opened_until

dateTime

Filter bookmarks by date opened (until this date).

archived_since

dateTime

Filter bookmarks by date archived (since this date).

archived_until

dateTime

Filter bookmarks by date archived (until this date).

favorited_since

dateTime

Filter bookmarks by date favorited (since this date).

favorited_until

dateTime

Filter bookmarks by date favorited (until this date).

updated_since

dateTime

Filter bookmarks by date updated (since this date).

updated_until

dateTime

Filter bookmarks by date updated (until this date).

order

string

One of:

  • -date_added
  • date_added
  • -date_updated
  • date_updated
What to order these bookmarks by. Default is date_added descending (-date_added).

page

integer

For pagination, what page of the results you are on. Default is 1.

per_page

integer

For pagination, how many results to return per page. Default is 20. Max is 50.

exclude_accessibility

string

One of:

  • favorites
  • latest
This parameter is deprecated and should no longer be used.

only_deleted

integer

One of:

  • 0
  • 1
If only_deleted is 1, this will return the bookmark IDs that have been deleted from this user's store. This is useful for synchronization of bookmarks. Note that a deleted bookmark does not contain article or tag information. The representation of a deleted bookmark in the bookmarks collection is described in the only deleted bookmarks representation.

tags

string

Comma separated string of tags to filter returned bookmarks. Values should be URL encoded.


Single tag example: tags=music


Single tag with spaces: tags=new%20york


Multiple tags: tags=music%2Cnew%20york


Multiple tags wil return bookmarks that contain all of the given tags (AND logic).


If used with only_deleted, it will be ignored.

available response representations:

POST

Add a bookmark. Returns 202 Accepted if a bookmark for this url did not exist or 409 Conflict if one already exists. Does not guarantee that an article for the given url will be parsed succesfully.
request query parameters
parametervaluedescription

url

anyURI (required)

The URL of the article to associate the bookmark with.

favorite

integer

Whether this article is favorited or not. 1 (true) or 0 (false).

archive

integer

Whether this article is archived or not. 1 (true) or 0 (false).

allow_duplicates

integer

Whether the bookmark should be recreated if it already exists. 1 (true) or 0 (false). Will return a 201 Created or 202 Accepted if the bookmark was recreated.
request header parameters
parametervaluedescription

Content-Type

string (required)

A value of application/x-www-form-urlencoded must be provided.

acceptable request representations:

response header parameters
parametervaluedescription

Location

anyURI

X-Article-Location

anyURI

potential faults:

/bookmarks/{bookmark_id}

Methods

GET

Retrieve a single bookmark. Note: date_opened is now deprecated and should not be used.

available response representations:

potential faults:

POST

Update a bookmark. Returns 200 on successful update.
request query parameters
parametervaluedescription

favorite

integer

Whether this article is favorited or not. 1 (true) or 0 (false).

archive

integer

Whether this article is archived or not. 1 (true) or 0 (false).

read_percent

float

The read progress made in this article, where 1.0 means the bottom and 0.0 means the very top. Expressed as a ratio of the document length, from the top of the browser window, unless the window is at the bottom.
request header parameters
parametervaluedescription

Content-Type

string (required)

A value of application/x-www-form-urlencoded must be provided.

acceptable request representations:

available response representations:

potential faults:

DELETE

Remove a single bookmark from this user's history. This is particularly for the case where a user accidentally bookmarks something they have no intention of reading. In almost all cases, you'll probably want to use archive by POSTing archive=1 to this bookmark.

Returns a 204 on a successful delete.

potential faults:

/bookmarks/{bookmark_id}/tags

Methods

POST

Add Tags to a bookmark.

There's currently limits on the number of Tags a user can have as well as the number of Tags that can be applied to a single Bookmark. Those limits are currently set to 500 and 20 respectively.

If a request to add Tags to a Bookmark creates enough new Tags for a User to exceed the limit, a 403 will be returned with a 'This user cannot add anymore Tags.' message.

If a request to add Tags to a Bookmark would cause the Bookmark limit (20) to be exceeded, a 403 will be returned with a 'No more Tags can be added to this Bookmark.' message.

Successful creation will result in a 202 as well as data on all Tags that were applied to the Bookmark.

Note that this is the only place when dealing with a Bookmark's tags that an `applied_count` attribute will be included. Normally, this is only provided when dealing with a User's set of Tags. It is included here as a convenience to update the applied count for Tags if the count is currently being displayed. A good example is the left side of the Reading List view on readability.com.

request query parameters
parametervaluedescription

tags

string (required)

Comma separated tags to be applied to the new bookmark. Readability will handle deduping with Tags that are already applied to the Bookmark.

available response representations:

potential faults:

/bookmarks/{bookmark_id}/tags/{tag_id}

Methods

DELETE

Delete a Tag from a bookmark. Returns a 204 on a successful delete.

potential faults:

/tags

Methods

GET

Retrieve all Tags for the current user. Response includes the Tag's text, applied count, ID, and a list of Bookmark IDs that the Tag is applied to.

Tags will be ordered by applied count and alphabetically.

available response representations:

potential faults:

/tags/{tag_id}

Methods

GET

Retrieve data on a single Tag. The requested Tag must belong to the current user. If a Tag for another user is requested, a 403 will be returned.

available response representations:

potential faults:

DELETE

Delete an entire Tag for a user. The requested Tag must belong to the current user. If a Tag for another user is requested, a 403 will be returned.

Please note that this deletes the Tag from all bookmarks to which it has been applied.

Returns a 204 on a successful delete.

potential faults:

Representations

Example root representation. (application/json)

{
    "resources": {
        "bookmarks": {
            "description": "The Bookmarks Collection Resource",
            "href": "/api/rest/v1/bookmarks"
        },
        "tags": {
            "description": "The Tags Collection Resource",
            "href": "/api/rest/v1/tags"
        }
    }
}

Example article representation. (application/json)

{
    "domain": "www.newyorker.com",
    "next_page_href": null,
    "author": "Tim Parks",
    "url": "http://www.newyorker.com/arts/critics/atlarge/2011/04/11/110411crat_atlarge_parks?currentPage=all",
    "lead_image_url": "http://www.newyorker.com/images/2011/04/11/p233/110411_r20743_p233.jpg",
    "content_size": 29426,
    "title": "Booted",
    "excerpt": "Italian voters used to be charmed by Berlusconi’s libertine ways. Anniversaries are uplifting when you have something to c",
    "direction": "ltr",
    "word_count": 4291,
    "content": "<div><p>[article content here]</p></div>",
    "date_published": "2011-04-11 00:00:00",
    "dek": "What really ails Italy?",
    "processed": true,
    "short_url": "http://rdd.me/47g6s8e7",
    "id": "47g6s8e7"
}

Example bookmarks representation. (application/json)

{
    "conditions": {
        "opened_since": null,
        "added_until": null,
        "opened_until": null,
        "archived_until": null,
        "favorite": null,
        "archived_since": null,
        "favorited_since": null,
        "user": "jdoe",
        "per_page": 2,
        "favorited_until": null,
        "archive": null,
        "added_since": null,
        "order": "-date_added",
        "page": 1,
        "updated_since": null,
        "updated_until": null
    },
    "meta": {
        "num_pages": 38,
        "page": 1,
        "item_count_total": 76,
        "item_count": 2
    },
    "bookmarks": [
        {
            "user_id": 1,
            "read_percent": "0.0",
            "date_updated": "2010-10-12 11:38:39",
            "favorite": false,
            "article": {
                "domain": "adobe.com",
                "excerpt": "This is an excerpt of the article text, 200 chars or less&hellip;",
                "word_count": 3482,
                "processed": true,
                "id": 87,
                "title": "A brief overview of the Spark architecture and component set"
                "lead_image_url": "http://www.adobe.com/images/2011/04/11/p233/110411_r20743_p233.jpg",
                "author": "John Smith",
                "direction": "ltr",
                "date_published": "2011-04-11 00:00:00",
                "dek": null,
                "url": "http://www.adobe.com/devnet/flex/articles/flex4_sparkintro.html"
            },
            "id": 76,
            "date_archived": null,
            "date_opened": null,
            "date_added": "2010-10-12 11:38:29",
            "article_href": "/api/rest/v1/articles/87/",
            "date_favorited": null,
            "archive": false,
            "tags": [{"text": "adobe", "id": 123}, {"text": "John Smith", "id": 456}]
        },
        {
            "user_id": 1,
            "read_percent": "0.13",
            "date_updated": "2010-10-12 11:04:46",
            "favorite": false,
            "article": {
                "domain": "w3.org",
                "excerpt": "This is an excerpt of the article text, 200 chars or less&hellip;",
                "word_count": 3482,
                "processed": true,
                "id": 86,
                "title": "Web Application Description Language"
                "lead_image_url": null,
                "author": null,
                "direction": "ltr",
                "date_published": null,
                "dek": null,
                "url": "http://www.w3.org/Submission/wadl/"
            },
            "id": 75,
            "date_archived": null,
            "date_opened": null,
            "date_added": "2010-10-12 11:04:46",
            "article_href": "/api/rest/v1/articles/86/",
            "date_favorited": null,
            "archive": false,
            "tags": []
        }
    ]
}

Example deleted bookmarks representation. (application/json)

{
    "bookmarks": [
        {
            "user_id": 1,
            "read_percent": "0.00",
            "date_updated": "2011-12-07 13:42:06",
            "favorite": true,
            "article": null,
            "id": 486,
            "date_archived": null,
            "deleted": true,
            "date_opened": null,
            "date_added": "2011-12-05 17:27:32",
            "article_href": null,
            "date_favorited": "2011-12-05 17:37:45",
            "archive": false
        },
        {
            "user_id": 1,
            "read_percent": "0.00",
            "date_updated": "2011-12-12 09:43:54",
            "favorite": false,
            "article": null,
            "id": 481,
            "date_archived": null,
            "deleted": true,
            "date_opened": null,
            "date_added": "2011-02-23 00:00:00",
            "article_href": null,
            "date_favorited": null,
            "archive": false
        }
    ],
    "meta": {
        "num_pages": 1,
        "page": 1,
        "item_count_total": 2,
        "item_count": 2
    },
    "conditions": {
        "opened_since": null,
        "favorited_since": null,
        "domain": "",
        "updated_until": null,
        "exclude_accessibility": "",
        "archived_until": null,
        "favorite": null,
        "opened_until": null,
        "archived_since": null,
        "added_until": null,
        "updated_since": null,
        "user": "jdoe",
        "per_page": 20,
        "favorited_until": null,
        "order": "-date_added",
        "only_deleted": 1,
        "archive": null,
        "added_since": null,
        "page": 1
    }
}

Example Bookmarks POST Representation (application/x-www-form-urlencoded)

url=http%3A%2F%2Fwww.w3.org%2FSubmission%2Fwadl%2F&favorite=1&archive=0&tags=w3%2Cweb

Example bookmark representation. (application/json)

{
    "user_id": 1,
    "read_percent": "0.13",
    "date_updated": "2010-10-12 11:04:46",
    "favorite": false,
    "article": {
        "domain": "www.newyorker.com",
        "title": "Booted",
        "url": "http://www.newyorker.com/arts/critics/atlarge/2011/04/11/110411crat_atlarge_parks?currentPage=all",
        "lead_image_url": "http://www.newyorker.com/images/2011/04/11/p233/110411_r20743_p233.jpg",
        "author": "Tim Parks",
        "excerpt": "Italian voters used to be charmed by Berlusconi&#x2019;s libertine ways. Anniversaries are uplifting when you have something to &hellip;",
        "direction": "ltr",
        "word_count": 4291,
        "date_published": "2011-04-11 00:00:00",
        "dek": "What really ails Italy?",
        "processed": true,
        "id": "47g6s8e7"
    },
    "id": 75,
    "date_archived": null,
    "date_opened": null,
    "date_added": "2010-10-12 11:04:46",
    "article_href": "/api/rest/v1/articles/86/",
    "date_favorited": null,
    "archive": false,
    "tags": [{"text": "w3", "id": 123}, {"text": "web", "id": 456}]
}

Example Bookmark POST Representation (application/x-www-form-urlencoded)

favorite=1&archive=0&read_percent=0.2&tags=new%20yorker%2Celections

Example Bookmark Tags representation. (application/json)

{
    "tags": [
      {"id": 123, "text": "news"},
      {"id": 456, "text": "Apple},
      {"id": 978, "text": "ALL CAPS TAG"},
      {"id": 44, "text": "new yorker"}
    ]
}

Example Bookmarks Tags POST representation. (application/json)

{
    "tags": [
      {"id": 123, "text": "news", "applied_count": 4},
      {"id": 456, "text": "Apple", "applied_count": 6},
      {"id": 978, "text": "ALL CAPS TAG", "applied_count": 3},
      {"id": 44, "text": "new yorker", "applied_count": 5}
    ]
}

Example Tags representation. (application/json)

{
    "tags": [
      {"id": 123, "text": "news", "applied_count": 3, "bookmark_ids": [1, 34, 539]},
      {"id": 456, "text": "Apple", "applied_count": 3, "bookmark_ids": [54, 31, 59]},
      {"id": 978, "text": "ALL CAPS TAG", "applied_count": 3, "bookmark_ids": [61, 34, 39]},
      {"id": 44, "text": "new yorker", "applied_count": 3, "bookmark_ids": [1, 4, 539]}
    ]
}

Example Tag representation. (application/json)

{
    "id": 123, "text": "news", "applied_count": 3, "bookmark_ids": [1, 34, 539]
}

Example user representation for the current user. (application/json)

{
    "username": "jdoe",
    "first_name": "John",
    "last_name": "Doe",
    "date_joined": "2010-10-08 12:00:17",
    "has_active_subscription": false,
    "reading_limit": 20,
    "email_into_address": "jdoe+crumb@inbox.readability.com",
    "kindle_email_address": "johndoe@kindle.com",
    "tags": [
        {"text": "music",    "applied_count": 1, "id": 123, "bookmark_ids": [4]},
        {"text": "New York", "applied_count": 3,  "id": 46, "bookmark_ids": [12, 45, 99]}
    ]
}

Errors

401 Authorization Required (application/json)

Authentication failed or was not provided. Verify that you have sent valid credentials.

404 Not Found (application/json)

The resource that you requested does not exist.

500 Internal Server Error (application/json)

An unknown error has occurred.

400 Bad Request (application/json)

The server could not understand your request. Verify that request parameters (and content, if any) are valid.

403 Forbidden (application/json)

The server understood your request and verified your credentials, but you are not allowed to perform the requested action.