API

The Tumblr API is implemented over standard HTTP requests. This allows Tumblr to be integrated with just about any application that can connect to the web.

Contents

/api/read

Reading Tumblr data is easy: just fetch the page at http://(you).tumblr.com/api/read and you'll get a structured XML version of your content in this format:

<tumblr version="1.0">
    <tumblelog ... >
        ...
        <feeds>
            <feed ... />
            <feed ... />
            ...
        </feeds>
    </tumblelog>
    <posts>
        <post type="regular" ... >
            <regular-title>...</regular-title>
            <regular-body>...</regular-body>
        </post>
        <post type="link" ... >
            <link-text>...</link-text>
            <link-url>...</link-url>
        </post>
        <post type="quote" ... >
            <quote-text>...</quote-text>
            <quote-source>...</quote-source>
        </post>
        <post type="photo" ... >
            <photo-caption>...</photo-caption>
            <photo-url max-width="500">...</photo-url>
            <photo-url max-width="400">...</photo-url>
            ...
        </post>
        <post type="conversation" ... >
            <conversation-title>...</conversation-title>
            <conversation-text>...</conversation-text>
            <conversation>
                <line name="..." label="...">...</line>
                <line name="..." label="...">...</line>
                ...
            </conversation>
        </post>
        <post type="video" ... >
            <video-caption>...</video-caption>
            <video-source>...</video-source>
            <video-player>...</video-player>
        </post>
        <post type="audio" ... >
            <audio-caption>...</audio-caption>
            <audio-player>...</audio-player>
        </post>
        ...
    </posts>
</tumblr>

The most recent 20 posts are included by default. You may pass these optional GET parameters:

  • start - The post offset to start from. The default is 0.
  • num - The number of posts to return. The default is 20, and the maximum is 50.
  • type - The type of posts to return. If unspecified or empty, all types of posts are returned. Must be one of text, quote, photo, link, chat, video, or audio.
  • id - A specific post ID to return. Use instead of start, num, or type.
  • filter - Alternate filter to run on the text content. Allowed values:
    • text - Plain text only. No HTML.
    • none - No post-processing. Output exactly what the author entered. (Note: Some authors write in Markdown, which will not be converted to HTML when this option is used.)
  • tagged - Return posts with this tag in reverse-chronological order (newest first). Optionally specify chrono=1 to sort in chronological order (oldest first).
  • search - Search for posts with this query.

For detailed example feeds, see the live Read API on Marco.org or the demo blog. A browser that pretty-prints XML, such as Firefox, is recommended.

JSON output

By using /api/read/json instead of /api/read when calling the Read API, the output will be sent as JSON assigned to a Javascript variable named tumblr_api_read. All regular Read API parameters are accepted, plus:

  • callback - A function name to call with the JSON object as its only parameter. When set, the function will be called instead of the tumblr_api_read variable being set.

Example:

<script type="text/javascript" src="http://(you).tumblr.com/api/read/json"></script>

<script type="text/javascript">
    // The variable "tumblr_api_read" is now set.
    document.write(
        '<a href="' + tumblr_api_read[1][0]['@url'] + 
        '">Most recent Tumblr post</a>'
    );
</script>

To view a human-readable map of the array's structure for easy reference, pass debug=1 as a GET parameter. The output will be like that of PHP's print_r() function.

Authenticated read

To include private posts in /api/read, use a POST request to /api/read and include the email and password parameters (see /api/write below) from an account authorized to view the blog's Dashboard.

Private posts are indicated in the resulting XML with the extra private="true" attribute on their <post> nodes.

/api/write

The Write API is a very simple HTTP interface. To create a post, send a POST request to http://www.tumblr.com/api/write with the following parameters:

  • email - Your account's email address.
  • password - Your account's password.
  • type - The post type.
  • (content parameters) - These vary by post type.
  • generator (optional) - A short description of the application making the request for tracking and statistics, such as "John's Widget 1.0". Must be 64 or fewer characters.
  • date (optional) - The post date, if different from now, in the blog's timezone. Most unambiguous formats are accepted, such as '2007-12-01 14:50:02'. Dates may not be in the future.
  • private (optional) - 1 or 0. Whether the post is private. Private posts only appear in the Dashboard or with authenticated links, and do not appear on the blog's main page.
  • tags (optional) - Comma-separated list of post tags. You may optionally enclose tags in double-quotes.
  • format (optional) - html or markdown.
  • group (optional) - Post this to a group instead of your blog. Value types:
    1. Domain, e.g. mygroup.tumblr.com (for public groups only)
    2. Group ID number, e.g. 1495028. Found with the Dashboard URL for that group, e.g. www.tumblr.com/group/1495028.

Post types

These are the valid values for the type parameter, with the associated content parameters that each type supports:

  • regular - Requires at least one:
    • title
    • body (HTML allowed)
  • photo - Requires either source or data, but not both. If both are specified, source is used.
    • source - The URL of the photo to copy. This must be a web-accessible URL, not a local file or intranet location.
    • data - An image file. See File uploads below.
    • caption (optional, HTML allowed)
    • click-through-url (optional)
  • quote
    • quote
    • source (optional, HTML allowed)
  • link
    • name (optional)
    • url
    • description (optional, HTML allowed)
  • conversation
    • title (optional)
    • conversation
  • video - Requires either embed or data, but not both.
    • embed - Either the complete HTML code to embed the video, or the URL of a YouTube video page.
    • data - A video file for a Vimeo upload. See File uploads below.
    • title (optional) - Only applies to Vimeo uploads.
    • caption (optional, HTML allowed)
  • audio
    • data - An audio file. Must be MP3 or AIFF format. See File uploads below.
    • externally-hosted-url (optional, replaces data) - Create a post that uses this externally hosted audio-file URL instead of having Tumblr copy and host an uploaded file. Must be MP3 format. No size or duration limits are imposed on externally hosted files.
    • caption (optional, HTML allowed)

File uploads

File uploads can be done in a data parameter where specified above. You may use either of the common encoding methods:

  • multipart/form-data method, like a file upload box in a web form. Maximum size:
    • 50 MB for videos
    • 10 MB for photos
    • 10 MB for audio
    This is recommended since there's much less overhead.
  • Normal POST method, in which the file's entire binary contents are URL-encoded like any other POST variable. Maximum size:
    • 5 MB for videos
    • 5 MB for photos
    • 5 MB for audio

Return values

We return standard HTTP status codes for each request, plus a plaintext response.

  • 201 Created - Success! The newly created post's ID is returned.
  • 403 Forbidden - Your email address or password were incorrect.
  • 400 Bad Request - There was at least one error while trying to save your post. Errors are sent in plain text, one per line.

Sample PHP code

<?php

// Authorization info
$tumblr_email    = 'info@davidville.com';
$tumblr_password = 'secret';

// Data for new record
$post_type  = 'regular';
$post_title = 'The post title';
$post_body  = 'This is the body of the post.';

// Prepare POST request
$request_data = http_build_query(
    array(
        'email'     => $tumblr_email,
        'password'  => $tumblr_password,
        'type'      => $post_type,
        'title'     => $post_title,
        'body'      => $post_body,
        'generator' => 'API example'
    )
);

// Send the POST request (with cURL)
$c = curl_init('http://www.tumblr.com/api/write');
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, $request_data);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($c);
$status = curl_getinfo($c, CURLINFO_HTTP_CODE);
curl_close($c);

// Check for success
if ($status == 201) {
    echo "Success! The new post ID is $result.\n";
} else if ($status == 403) {
    echo 'Bad email or password';
} else {
    echo "Error: $result\n";
}

?>

If you have trouble, please ensure that you are properly encoding the POST parameters. If you have any other questions, please pass them along to Tumblr Support.

Editing posts

To edit a post, create the /api/write request as described above, and pass an additional POST parameter:

  • post-id - The integer ID of the post you wish to edit.

Pass all other parameters normally as you would with /api/write, specifying their new values, with the following exceptions:

  • type, private, format - These are ignored and can be omitted. These values cannot be changed after post creation.
  • tags, generator, date - These are optional. If specified, the new values will override the previous values. If omitted, the values are not changed.

Deleting posts

To edit a post, create the authenticated /api/write request as described above, but POST to http://www.tumblr.com/api/delete instead, and pass an additional POST parameter:

  • post-id - The integer ID of the post you wish to delete.

All content-related parameters will be ignored and can be omitted. Only the authentication parameters and post-id are required.

/api/authenticate

Send a POST request to http://www.tumblr.com/api/authenticate with only the email and password parameters to validate credentials and get account information, such as user limits and blogs.

The output is XML. The root <tumblr> element contains one child <user> node, plus one child <tumblelog> element per blog membership (including the user's default blog).

Attributes on <user>:

  • can-upload-audio: "1" if the user can currently upload an MP3 audio file.
  • can-upload-aiff: "1" if the user can currently upload an AIFF audio file.
  • can-upload-video: "1" if the user can currently upload video. Requires the user to be logged into Vimeo through Tumblr.
  • max-video-bytes-uploaded: Indicates the maximum number of bytes for the user's next video upload. Requires the user to be logged into Vimeo through Tumblr.

Attributes on <tumblelog>:

  • title
  • type: public or private
  • private-id (private blogs only): The ID number for private blogs. Use this value for the group parameter on /api/write.
  • name (public blogs only)
  • url (public blogs only)
  • avatar-url (public blogs only)
  • is-primary: yes if this is the user's primary/default blog

Deprecated

The following values of action are deprecated and may be removed in the future.

  • list-tumblelogs
  • check-vimeo
  • check-audio

Their functionality is now included in /api/authenticate.

iPhone

For iPhone apps that want to display a user's Dashboard, Tumblr offers an iPhone-optimized view at http://www.tumblr.com/iphone.

To avoid making the user log into Tumblr separately if you already have their credentials, you can send an HTTP POST to http://www.tumblr.com/login (see Tumblr's login system) with these form-encoded parameters:

  • email
  • password
  • redirect_to: the relative destination URL to open after a successful login

Example Cocoa code:

NSString *email           = @"example@email.com";
NSString *password        = @"password";
NSString *destination_url = @"/iphone";

NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
    initWithURL:[NSURL URLWithString:@"http://www.tumblr.com/login"]
];
[request setHTTPMethod:@"POST"];
NSString *request_body = [NSString 
    stringWithFormat:@"email=%@&password=%@&redirect_to=%@",
    [email           stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
    [password        stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
    [destination_url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
];
[request setHTTPBody:[request_body dataUsingEncoding:NSUTF8StringEncoding]];
/* Load the request here with an NDA-covered iPhone component
   that can view the web.
*/
[request release];

Tumblr's login system

Most applications for creating, editing, and reading post data will not need to interact with Tumblr's standard browser-based login system at http://www.tumblr.com/login.

If your application uses only /api/read and/or /api/write, you never need to worry about cookies or login limits.

If your application submits credentials to http://www.tumblr.com/login, you will be issued a login cookie. Please keep in mind:

  • Login cookies can expire or be invalidated outside of your application. They cannot be guaranteed or checked. In most cases, using an invalid login cookie on a page requiring a login will result in an HTTP redirect to http://www.tumblr.com/login.
  • Users are only issued a limited number of login cookies before the oldest issued cookies are invalidated. Therefore, please do not consume unnecessary login cookies, especially if you do not retain them between requests. This will result in the user being frequently logged out of their normal browser-based logins.
  • If your app sends a POST login to http://www.tumblr.com/login but it supplies a valid login cookie, a duplicate will not be issued. This is the recommended practice for showing a Dashboard page in an embedded browser, such as the iPhone example, because it won't consume unnecessary login tickets for the user but it will always result in a valid login (with correct credentials).

Please do not use the http://www.tumblr.com/login system if your desired functionality can be accomplished with /api/read or /api/write.

Use of the http://www.tumblr.com/login system is unsupported and subject to change without notice.