Full Developer API

The Instapaper API allows third-party applications to add URLs to Instapaper. If you only need to add URLs from your application to an Instapaper customer's account, consider using the Simple API.

Use of the API constitutes agreement to the API Terms of Use. Please read it, really. It's short and contains important implementation rules.

If you find a bug, or a minor change in the API could make your life a lot easier, please send feedback.

Overview

This API has been designed for ease of implementation. All methods and requirements are intentionally kept very simple, with one exception: almost all functionality requires OAuth.

OAuth

I know OAuth can be daunting, but there are a lot of helper libraries available. I believe the benefits to both Instapaper and its users are worth the OAuth hurdle.

Instapaper's OAuth implementation is different from what you may be accustomed to: there is no request-token/authorize workflow. This makes it much simpler. Instead, Instapaper uses an implementation of xAuth very similar to Twitter's. So you still need to sign your requests, but getting tokens is simple.

xAuth is the only way to get an Instapaper access token.

Other details:

  • Only the HMAC-SHA1 signature method is supported.
  • HTTPS is required on all endpoints. HTTP support is deprecated as of April 1st 2014, and will not be supported as of June 1st 2014. If you are currently using HTTP requests, please take the necessary steps to enable HTTPS on all API requests prior to June 1st.
  • All requests should be made via the POST method, and all parameters should be passed in the POST request-body and not in the query-string.
  • The OAuth parameters should be passed in the Authorization: header, not in the query-string or request-body.
  • Account usernames may change. When storing a reference to accounts, you should store the numeric user_id when possible, and only use the username for display purposes. On methods that return a copy of the user object for the current account, such as bookmarks/list, check the username value to see if it has changed and record the change in your application as necessary.
Get a token for your application

To get an OAuth consumer token for your application, fill this out.

All token requests are reviewed by a human before being activated.

Subscription accounts

Most of the Full API's methods require the authenticating user to have a Subscription account.

Only these methods may be used for users without a Subscription:

  • /api/1.1/oauth/access_token
  • /api/1.1/account/verify_credentials
  • /api/1.1/bookmarks/add
  • /api/1.1/folders/list
  • /api/1.1/bookmarks/<bookmark-id>/highlight *

*Limit of 5 highlights per month for non-subscribers.

Effectively, any application that only needs to add pages to someone's Instapaper account, like a Twitter client or RSS reader, can function completely with these methods, and therefore does not require its users to have Instapaper Subscriptions.

Note: If you only need these methods and prefer a simpler implementation without OAuth, consider using the Simple API.

Users with Subscriptions are required for the deeper functionality that full Instapaper clients and other complex applications require.

Instapaper is self-funded and pays nearly all of its expenses with revenue from the Instapaper iPhone app and the ads on the website, but customers using these advanced API methods may never buy the iPhone app or visit the website. Subscriptions cover the cost of hosting these API methods.

Output formats

Instapaper strings are always encoded in UTF-8, and Instapaper expects all input to be in UTF-8.

Unless otherwise noted, output from every method is an array. The output array is returned as JSON by default.

  • You can specify a jsonp parameter with a callback function name, e.g. jsonp=myCallback, to use JSONP and wrap the output in a call to the specified function.

Each item in the array is an associative array (a hash) containing simple named parameters, each with a type key to describe it. Possible type values:

  • user: An Instapaper user account.
  • bookmark: A saved article.
  • folder: A folder.
  • error: An error.
  • meta: Response metadata, where available.

Example output:

[
    {
        "type":"user",
        "user_id":543210,
        "username":"TestUserOMGLOL"
    },
    {
        "type":"bookmark",
        "bookmark_id":1234,
        "url":"http:\/\/www.example.com\/page1.html",
        "title":"Example page 1",
        "description":"An example page."
    },
    {
        "type":"bookmark",
        "bookmark_id":1235,
        "url":"http:\/\/www.example.com\/page2.html",
        "title":"Example page 2",
        "description":"Another example page."
    },
    {
        "type":"highlight",
        "highlight_id":42,
        "bookmark_id":1234,
        "text":"example page",
        "position":0,
        "time":1394470555
    }
]


Errors are returned in the same way whenever possible, e.g.:

[{"type":"error", "error_code":1240, "message":"Invalid URL specified"}]

The message value in errors is meant to assist programmers during development and debugging, and is not intended to be displayed to users.

If the response is not valid JSON, it should be interpreted as an HTTP 503 "Service Temporarily Unavailable" error, and the request should be retried later.

The qline format

qline support is deprecated as of version 1.1 of the API. Please use JSON for all endpoints.

A simple custom format called qline is also supported for environments without convenient JSON decoding, but with a URL-decode string function. (If anyone ever asks, the way to pronounce it is "Queue-Line", because it's short for Query-String Line.)

Append the optional parameter format=qline in the API call to get qline output.

This format encodes Instapaper's array items as lines, separated by a standard \n newline character, with each line being encoded like a URL query-string. For example:

type=user&user_id=543210&username=TestUserOMGLOL
type=bookmark&bookmark_id=1234&url=http%3A%2F%2Fwww.example.com%2Fpage1.html&title=Example%20page%201&description=An%20example%20page.
type=bookmark&bookmark_id=1235&url=http%3A%2F%2Fwww.example.com%2Fpage2.html&title=Example%20page%202&description=Another%20example%20page.
type=bookmark&bookmark_id=1236&url=http%3A%2F%2Fwww.example.com%2Fpage3.html&title=Example%20page%203&description=Yet%20another%20example%20page.

Errors work the same way:

type=error&error_code=1240&message=Invalid%20URL%20specified

These can be quickly decoded with this pseudocode algorithm:

objects = {}
for each line in input.split("\n"):
    attributes = {}
    for each pair in line.split("&"):
        parts = pair.split("=");
        attributes[parts[0]] = url_decode(parts[1]);

    if (attributes[type] is set) objects.append(attributes)

return objects

Empty lines should be ignored. If the response is not parseable, or has no recognizable objects with known type values, it should be interpreted as an HTTP 503 "Service Temporarily Unavailable" error, and the request should be retried later.

Account methods
/api/1/oauth/access_token

Gets an OAuth access token for a user.

Input parameters:

  • x_auth_username: The user's username.
  • x_auth_password: The user's password, if the account has one.
  • x_auth_mode: Must be the value "client_auth".

Output on success: A single-line qline-like output (not JSON, to match conventions when issuing access tokens) with the OAuth access token and secret to use, e.g.:

oauth_token=aabbccdd&oauth_token_secret=efgh1234

Generated tokens and secrets are currently each up to 50 characters long. They are case-sensitive and may contain letters and numbers, but will not contain other symbols.

/api/1/account/verify_credentials

Returns the currently logged in user.

Output on success: A user object, e.g.

[{"type":"user","user_id":54321,"username":"TestUserOMGLOL"}]
Bookmark methods
/api/1/bookmarks/list

Lists the user's unread bookmarks, and can also synchronize reading positions.

Input parameters:

  • limit: Optional. A number between 1 and 500, default 25.
  • folder_id: Optional. Possible values are unread (default), starred, archive, or a folder_id value from /api/1.1/folders/list.
  • have: Optional. A concatenation of bookmark_id values that the client already has from the specified folder. See below.
  • highlights: Optional. A '-' delimited list of highlight IDs that the client already has from the specified bookmarks.

Output: A JSON object, not the standard API output structures, with format:

{
    "user":{<user object>},
    "bookmarks":[{<bookmark 1>}, ... ],
    "highlights":[{<highlight 1>}, ... ],
    "delete_ids":[<list of deleted bookmark IDs>]
}


Warning: HTML in highlight text is returned unescaped through the API.

The "have" parameter:

This is a comma-separated list of bookmark_id values that the client already has in its local bookmark data, and shouldn't be re-sent. Any IDs sent in the have parameter that would not have appeared in the list within the given limit are returned in a delete_ids parameter on the meta object.

The have parameter can just be a list of the bookmark_id values, e.g.:

12345,12346,12347

...in which case Instapaper won't include those bookmarks in the output.

But it can also do more. Each bookmark returned by the API has a hash value, which is computed from its URL, title, description, and reading progress. If you join the hash value you have for an article with its article ID using a colon, e.g.:

12345:OjMuzFp6,12346:0n4ONgYs,12347:YXo82wTR

...then Instapaper will omit those bookmarks from the output, but only if the hashes haven't changed. So you can use this method to selectively be informed of updates to article metadata without otherwise re-downloading the entire list on each update.

Finally, you can optionally append two more fields to each ID with colons to indicate how far the user has read each article, as a floating-point value between 0.0 and 1.0 to indicate progress and the Unix timestamp value of the time that the progress was recorded, e.g.:

12345:OjMuzFp6:0.5:1288584076

This would indicate that the bookmark with bookmark_id=12345 and hash=OjMuzFp6 was read to 0.5 progress, or 50% of its length, at timestamp 1288584076 (2010-11-01 12:01:16am EST). If the server's information is less recent than this, it will update the bookmark and return it in the output with a new hash value.

/api/1/bookmarks/update_read_progress

Updates the user's reading progress on a single article. This functionality is included in the have parameter of the /api/1.1/bookmarks/list operation above, but this method exists in case you want to call it separately.

Input parameters:

  • bookmark_id: The bookmark to update.
  • progress: The user's progress, as a floating-point number between 0.0 and 1.0, defined as the top edge of the user's current viewport, expressed as a percentage of the article's total length.
  • progress_timestamp: The Unix timestamp value of the time that the progress was recorded.

Output: The modified bookmark on success.

/api/1/bookmarks/add

Adds a new unread bookmark to the user's account.

Input parameters:

  • url: Required, except when using private sources (see below).
  • title: Optional. If omitted or empty, the title will be looked up by Instapaper synchronously. This will delay the action, so please specify the title if you have it.
  • description: Optional. A brief, plaintext description or summary of the article. Twitter clients often put the source tweet's text here, and Instapaper's bookmarklet puts the selected text here if the user has selected any.
  • folder_id: Optional. The integer folder ID as returned by the folder/list method described below.
  • resolve_final_url: Optional, default 1. Specify 1 if the url might not be the final URL that a browser would resolve when fetching it, such as if it's a shortened URL, it's a URL from an RSS feed that might be proxied, or it's likely to go through any other redirection when viewed in a browser. This will cause Instapaper to attempt to resolve all redirects itself, synchronously. This will delay the action, so please specify 0 for this parameter if you're reasonably confident that this URL won't be redirected, such as if it's already being viewed in a web browser.

Output: The bookmark on success, which may not be new: if this user already saved this URL, it will be moved to the top of the Unread list (or the specified folder) and assigned the new values for title, description, and content (see below).

In addition to standard invalid-parameter errors, you may encounter these special errors:

  • 1220: Domain requires full content to be supplied -- Pages from this domain require the content parameter below, usually because a login or subscription is required to get their content, and you haven't supplied it. If you already have the page loaded in a browser environment, simply re-submit with the body contents (e.g. Javascript's document.body.innerHTML). If not, you may need to open it in a browser first, or give the user a helpful message explaining that content from this site needs to be viewed in a browser before saving to Instapaper.
  • 1221: Domain has opted out of Instapaper compatibility -- The publisher of this domain has requested that Instapaper not save any of its content. Do not attempt to work around this, which is prohibited in the API Terms of Use. Please give the user a helpful message, where applicable, that the publishers of this site do not permit Instapaper usage.
Supplying HTML content for a bookmark

You can optionally supply the full HTML content of pages that Instapaper wouldn't otherwise be able to crawl from its servers, such as pages that require logins or subscriptions.

  • content: The full HTML content of the page, or just the <body> node's content if possible, such as the value of document.body.innerHTML in Javascript. Must be UTF-8.

A bookmark's content is not shared to other users through any sharing functionality (such as Starred-folder subscriptions). It is only used to generate the text version of the bookmark for the user that created it.

This is not for material that doesn't have a dedicated, permanent URL or should be excluded from sharing and tracking functionality completely, such as a private message on a social network, driving directions, or the results of a session. For that, see "Private sources" below.

Private sources

Bookmarks can be private, such as the bookmarks that result from Instapaper's email-in text feature. Private bookmarks are not shared to other users through any sharing functionality (such as Starred-folder subscriptions), and they do not have URLs.

Set this parameter to a non-empty string to set a bookmark to private:

  • is_private_from_source: A short description label of the source of the private bookmark, such as "email" or "MyNotebook Pro".

When using this, values passed to url will be ignored, and the content parameter (above) is required.

In any bookmark objects output by this API, the private_source field will be an empty string for public bookmarks, and this value for private bookmarks. They will have an automatically generated, non-functioning value in the url field of the form instapaper://private-content/.... Do not use these URLs in your application.

/api/1/bookmarks/delete

Permanently deletes the specified bookmark. This is NOT the same as Archive. Please be clear to users if you're going to do this.

Input parameter: bookmark_id

Output: An empty array on success.

/api/1/bookmarks/star

Stars the specified bookmark.

Input parameter: bookmark_id

Output: The modified bookmark on success.

/api/1/bookmarks/unstar

Un-stars the specified bookmark.

Input parameter: bookmark_id

Output: The modified bookmark on success.

/api/1/bookmarks/archive

Moves the specified bookmark to the Archive.

Input parameter: bookmark_id

Output: The modified bookmark on success.

/api/1/bookmarks/unarchive

Moves the specified bookmark to the top of the Unread folder.

Input parameter: bookmark_id

Output: The modified bookmark on success.

/api/1/bookmarks/move

Moves the specified bookmark to a user-created folder.

Input parameters: bookmark_id, folder_id

Output: The modified bookmark on success.

/api/1/bookmarks/get_text

Returns the specified bookmark's processed text-view HTML, which is always text/html encoded as UTF-8.

Input parameters: bookmark_id

Output: HTML with an HTTP 200 OK status, not the standard API output structures, or an HTTP 400 status code and a standard error structure if anything goes wrong.

Folder methods
/api/1/folders/list

Input parameters: None.

Output: A list of the account's user-created folders. This only includes organizational folders and does not include RSS-feed folders or starred-subscription folders, as the implementation of those is changing in the near future.

/api/1/folders/add

Creates an organizational folder.

Input parameters: title

Output: The newly created folder, or error 1250: "User already has a folder with this title" if the title isn't unique among this user's folders.

/api/1/folders/delete

Deletes the folder and moves any articles in it to the Archive.

Input parameter: folder_id

Output: An empty array on success.

/api/1/folders/set_order

Re-orders a user's folders.

Input parameter: order, a set of folder_id:position pairs joined by commas, where the position is a positive integer 32 bits or less. Example input, given the folder_ids 100, 200, and 300, wanting to order them in that order:

100:1,200:2,300:3

Or, to reverse their order:

100:3,200:2,300:1

The order of the pairs doesn't matter, only the position values do, so this is equivalent to the above value:

300:1,100:3,200:2

You must include all of the user's folders for consistent ordering. Invalid or missing folder IDs or positions will be ignored and will not return errors.

Output: The user's re-ordered folder list.

Highlight methods

/api/1.1/bookmarks/<bookmark-id>/highlights

List highlights for <bookmark-id>

Warning: HTML in highlight text is returned unescaped through the API.

Input parameters: None.

Output: An array of highlights for <bookmark-id>

/api/1.1/bookmarks/<bookmark-id>/highlight

Create a new highlight for <bookmark-id>

HTML tags in text parameter should be unescaped.

Note: Non-subscribers are limited to 5 highlights per month.

Input parameters:

  • text: The text for the highlight
  • position: Optional. The 0-indexed position of text in the content. Defaults to 0.

Output: The created highlight

/api/1.1/highlights/<highlight-id>/delete

Delete a highlight

Input parameters: None.

Output: None.

Errors

These are the most common errors you may receive.

General errors:

  • 1040: Rate-limit exceeded
  • 1041: Subscription account required
  • 1042: Application is suspended

Bookmark errors:

  • 1220: Domain requires full content to be supplied
  • 1221: Domain has opted out of Instapaper compatibility
  • 1240: Invalid URL specified
  • 1241: Invalid or missing bookmark_id
  • 1242: Invalid or missing folder_id
  • 1243: Invalid or missing progress
  • 1244: Invalid or missing progress_timestamp
  • 1245: Private bookmarks require supplied content
  • 1250: Unexpected error when saving bookmark

Folder errors:

  • 1250: Invalid or missing title
  • 1251: User already has a folder with this title
  • 1252: Cannot add bookmarks to this folder

Operational errors:

  • 1500: Unexpected service error
  • 1550: Error generating text version of this URL

Highlight Errors:

  • 1600: Cannot create highlight with empty text
  • 1601: Duplicate highlight
About Instapaper credentials

Every user has a unique username (doesn't have to be an email address, but often is). Passwords are not required, and most users do not have a password. Any interface prompting the user for credentials must accommodate this -- for example, you cannot assume that an empty password is a user error.

Authentication behavior:

  • If an account has a password and an incorrect one is supplied, authentication fails.
  • If an account does not have a password, any value works.
Preferred language

Wherever possible, please conform to the interface standards of your environment.

When prompting for the username, please label the field "Email or username", "Email address or username", or "Username". Do not label it only "Email", since many usernames are not email addresses.

If possible, when prompting for an Instapaper password, clarify that it is only required if they actually have a password. For example, on the website's login form, the box is labeled "Password, if you have one."

Suggested button or menu titles for the save-URL action: "Send to Instapaper", "Save to Instapaper", "Instapaper". Please avoid adding "you" or "me", e.g. "your Instapaper account", "my Instapaper", etc. in this context. (But that's fine when prompting for credentials.)

↑   Click & drag up to your Bookmarks Bar.