Tumblr Engineering (Posts tagged api)

1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

New, Bigger Post IDs

As some of you close watchers may have noticed, we recently updated the ID numbers for new posts on Tumblr to be huuuuuge. Post IDs were always 64-bit integers to us at Tumblr, but now they’re actually big enough to push into that bitspace. While this doesn’t change anything for anyone using the official Tumblr apps or website, it did cause some hiccups for third-party consumers using programming languages like Javascript, which support only 53 bits of precision for integers.

To help alleviate this, we’ve added a new field to our post objects via the Tumblr API called id_string, which is a string representation of the numeric post ID. You can use the value of this id_string instead of id in any request to the Tumblr API and it should work just the same. This is the same thing that Twitter did when they moved to big-number “snowflake” identifiers. Starting March 16th, you should see this new field whenever you encounter a post via the Tumblr API.

Why’d we change post IDs to be so huge? Some of you may have noticed there was quite a jump. We recently migrated Tumblr to a new datacenter, and as a part of that migration we updated the system that generates new post IDs. The new system generates much bigger IDs because it uses a different algorithm to generate them more safely.

If you run into trouble with this or don’t see it somewhere you need it, please contact Tumblr Support and we’ll take a look!

engineering post ids tumblr api api

New Public API and Neue Post Format Documentation

We’re abnormally jazzed to announce some significant updates to our public API and its documentation:

  • Our Tumblr API documentation has moved to Github in Markdown format. It also includes a few new things here and there, like a section on newer and better Blog Unique Identifiers.
  • The Neue Post Format is now available for use via the Tumblr API when consuming or creating posts! You can now make posts using a JSON specification that’s easier to use than HTML and will be more extensible moving forward as we build new ways of posting.
  • The new public documentation on Github now includes the JSON specification of the Neue Post Format to help you consume NPF and create Posts using NPF. We aren’t currently planning to deprecate the “Legacy” posting flows (yet), but at some point in the future we won’t be able to guarantee that HTML posts will look as intended on all devices and platforms.
  • Work on the Neue Post Format is ongoing here at Tumblr as we make the posting experience better, more streamlined, and more exciting; any changes we make will be documented in our new public docs on Github. Watch our new public doc repository to find out when these changes happen!
  • You can pass along the query parameter ?npf=true to any Tumblr API endpoint that returns Posts to return those Posts in the Neue Post Format rather than the legacy Post format.

To get started with our public API, register your own OAuth application and try using one of our Official API Clients! If you have any questions, please hit us up.

engineering api public api npf neue post format documentation

Golang and The Tumblr API

You’ve been asking for an official Golang wrapper for the Tumblr API. The wait is over! We are thrilled to unveil two new repositories on our GitHub page which can be the gateway to the Tumblr API in your Go project.

Why Two Repos

We’ve tried to structure the wrapper in a way that is as flexible as possible so we’ve put the meat of the library in one repo that contains the code for creating requests and parsing the responses, and interacts with an interface that implements methods for making basic REST requests.

The second repo is an implementation of that interface with external dependencies used to sign requests using OAuth. If you do not wish to include these dependencies, you may write your own implementation of the ClientInterface and have the wrapper library use that client instead.

Handling Dynamic Response Types

Go is a strictly typed language including the data structures you marshal JSON responses into. This means that the library could have surfaced response data as a map of string => interface{} generics which would require the engineer to further cast into an int, string, another map of string => interface{}, etc. The API Team decided to make it more convenient for you by providing typed response values from various endpoints.

If you have used the Tumblr API, you’ll know that our Post object is highly variant in what properties and types are returned based on the post type. This proved to be a challenge in codifying the response data. In Go, you’d hope to simply be able to define a dashboard response as an array of posts

type Dashboard struct {
  // ... other properties
  Posts []Post `json:"posts"`
}

However this would mean we’d need a general Post struct type with the union of all possible properties on a Post across all post types. Further complicating this approach, we found that some properties with the same name have different types across post types. The highest profile example: an Audio post’s player property is a string of HTML while a Video post’s player property is an array of embed strings. Of course we could type any property with such conflicts as interface{} but then we’re back to the same problem as before where the engineer then has to cast values to effectively use them.

Doing Work So You Don’t Have To

Instead, we decided any array of posts could in fact be represented as an array of PostInterfaces. When decoding a response, we scan through each post in the response and create a correspondingly typed instance in an array, and return the array of instances as an array of PostInterfaces. Then, when marshalling the JSON into the array, the data fills in to the proper places with the proper types. The end user can then interact with the array of PostInterface instances by accessing universal properties (those that exist on any post type) with ease. If they wish to use a type-specific property, they can cast an instance to a specific post type once, and use all the typed properties afterward.

This can be especially convenient when paired with Go’s HTML templating system:

snippet.go

// previously, we have some `var response http.ResponseWriter`
client := tumblrclient.NewClientWithToken(
    // ... auth data
)

if t,err := template.New("posts").ParseFiles("post.tmpl"); err == nil {
    if dash,err := client.GetDashboard(); err == nil {
        for _,p := range dash.Posts {
            t.ExecuteTemplate(response, p.GetSelf().Type, p.GetSelf())
        }
    }
}

post.tmpl

{{define "text"}}
<div>
    {{.Body | html}}
</div>
{{end}}
{{define "photo"}}
<div>
    Post: {{.Type}}
</div>
{{end}}
{{define "video"}}
<div>
    Post: {{.Type}}
</div>
{{end}}
{{define "audio"}}
<div>
    Post: {{.Type}}
</div>
{{end}}
{{define "quote"}}
<div>
    Post: {{.Type}}
</div>
{{end}}
{{define "chat"}}
<div>
    Post: {{.Type}}
</div>
{{end}}
{{define "answer"}}
<div>
    Post: {{.Type}}
</div>
{{end}}
{{define "link"}}
<div>
    Post: {{.Type}}
</div>
{{end}}

This is a rudimentary example, but the convenience and utility is fairly evident. You can define blocks to be rendered, named by the post’s type value. Those blocks can then assume the object in its named scope is a specific post struct and access the typed values directly.

Wrapping Up

This is a v1.0 release and our goal was to release a limited scope, but flexible utility for developers to use. We plan on implementing plenty of new features and improvements in the future, and to make sure that improvements to the API are brought into the wrapper. Hope you enjoy using it!

golang api