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
Instapaper's API uses OAuth 1.0a implementation, which requires signatures on requests. We recommend using an OAuth 1.0a library to help with signing the request.
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 thePOST
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 theusername
for display purposes. On methods that return a copy of theuser
object for the current account, such asbookmarks/list
, check theusername
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.
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 areunread
(default),starred
,archive
, or afolder_id
value from/api/1.1/folders/list
.have
: Optional. A concatenation ofbookmark_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 thefolders/list
method described below.resolve_final_url
: Optional, default1
. Specify1
if theurl
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 specify0
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 thecontent
parameter below, usually because a login or Instapaper Premium 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'sdocument.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 Instapaper Premium.
content
: The full HTML content of the page, or just the<body>
node's content if possible, such as the value ofdocument.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 highlightposition
: 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: Premium 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, which is almost always an email address. Passwords are not required, though most users do use one. 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".
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.)