Version 1.1 of the REST API

Today, we’ve launched version 1.1 of the REST API. In recent weeks, we’ve been hard at work launching new features on, and many of these changes are powered by our REST API. When we started working on the upgrades to stats and post management, we quickly realized that the existing endpoints didn’t have all the power we needed to provide the best experience. In order to add the functionality we needed to the API without breaking existing implementations, we decided to version our API.

What does this mean for you?

If you’re already implementing version 1 of the API, you’ll be able to continue using those endpoints without changing your code for the foreseeable future. Version 1 of the API is now deprecated, so any new development you do should be against 1.1. We currently have no plans to disable version 1 of the REST API — should we ever decide to do so, we’ll give you plenty of advanced notice.

Media Endpoints

  • Upload support for all file types. If you can you upload it though the media explorer, you can upload it with the API. PDFs, Docs, Powerpoints, Audio files, and Videos (Jetpack & .com blogs with VideoPress) are all supported.
  • Better error handling. If you upload multiple files and some fail, it’s easier to pull those out and retry.
  • Improved consistency with other endpoints and cleaned up response parameters.
  • When uploading files, you can now pass attributes like name and description without needing to do a second call to the update endpoint.
  • Bonus: The /sites/$site/ endpoint now returns a list of allowed file types.

Stats Endpoints

  • Support for pulling back stats over multiple days without those stats being grouped into a single result.
  • New stats detailing the top comment authors on your site, as well as the posts that have received the most comments.
  • In addition to chart data for views and visitors: chartable data about likes and comments.
  • Keep on track with your posting goals. The new streak endpoint contains the data to help motivate you to post more often.

We’re looking forward to seeing what you build using version 1.1. Take a look at the REST API documentation to get started. If you have any questions about the API, don’t hesitate to comment below or reach out to us via our developer contact form.

On API Correctness

Developing APIs is hard.

You pour your blood, sweat, and tears into this interface that bares the soul of your company and of your product to the world. The machinery under the hood, though, is often a lot less polished than the fancy paint job would lead the rest of the world to believe. You have to be careful, then, not to inflict your own rough edges on the people you expect to be consuming your API because…

Using APIs is hard.

As an app developer you’re trying to take someone else’s product and somehow integrate it into whatever vision you have in your head. Whether it’s simply getting a list of things from another service (such as embedding a reading list) or wrapping your entire product around another product (using Amazon S3 as your primary binary storage mechanism, for example), you have a lot of things to reconcile.

You have your own programming language (or languages) that you’re using. There’s the use case you have in mind, and the ones the remote devs had in mind for the API. There’s the programming language they used to create the API (and that they used to test it). Finally, don’t forget the encoding or representation of the data — and its limitations. Reconciling all of the slight (or major) differences between these elements is a real challenge sometimes. Despite years of attempts at best practices and industry standards, things just don’t always fit together like we pretend that they will.

As a developer providing an API it’s important to remember three things. There are obviously many other things to consider, but these three things are more universal than most.

#1 You want people to use your API.

Unless you’re developing a completely internal API, you’re hoping that the world sees your API as something amazing, and that your functionality starts popping up in other magical places without any further effort on your part.

#2 You have no control over what tools others are using.

Are you using a language that has little or no variable type enforcement? Some people aren’t. Some of those people still want to use your product. Did you come up with your own way of doing things with custom code instead of using widely-adopted industry standards (which, being widely deployed, come with battle-tested libraries in many languages)? Did that cause you to release a client in your own language (how about Clojure, how about Erlang, how about C++, how about Perl, how about…)?

#3 Your API is a promise.

It’s easy to forget (especially for those of us who spend our time in a forgiving language such as PHP or Python) that the API we provide is a promise to the rest of the world. What it promises is this: “When you provide me with ${this} I will provide you with ${that}”.

The super-important (and insidiously non-obvious) thing about this is that if you do not provide a written promise (in the form of your API’s documentation), then the behavior of your API becomes the implicit promise.

The most important thing to note here is that when your documentation is wrong, the promise of your actual behavior wins every single time.

Keep your promises

When your promises don’t match your actual results things get hairy.

Let’s take a look at a completely hypothetical situation.

  1. You have an API that is documented to return a json object with a success member which should be a boolean value.
  2. You have a case (maybe all cases) where success is actually rendered as an integer (0 for false, 1 for true).
  3. John has an app written in a strongly-typed language that works around this by defining success as an integer type instead of a boolean type. Because John was busy, he never got around to letting you know. Or maybe John never knew because he simply inspected your API and worked backwards from the responses that you gave. Now John’s app has 100k users depending on this functionality.
  4. Mary is writing an app, and because Mary doesn’t like to play fast and loose (and she doesn’t want her app to break later on) she submits an issue pointing out that you are returning the wrong type.

At this point you are trapped. The existing user base (and by extension their user base) is committed to integers. And you only have four options.

  1. You can cripple an existing and deployed application enjoyed by 100k users.
  2. You can version your API — an entire new version to correct what should be a boolean value.
  3. You can work with John to roll out a new version of the app which can handle both (but maybe his app is in the iOS app store, and getting everyone to update is impossible, takes a long time, and/or would require a lengthy, and potentially costly, review process by yet another party).
  4. You make a really sad face and change your promise — to reflect that you are going to do what is actually the less correct thing, forever.

Because you wrote an API whose promise was wrong, or whose promise was missing, you have painted yourself into a very undesirable corner. You’re now in a place where doing the right thing for the right reasons is the wrong move.

So do yourself, and everyone else, one of two favors — depending on the position in which you find yourself.

If you’re producing an API, take extra care to make sure that your results match your documentation (and you need to have documentation).

If you’re consuming an API, don’t be like John. Don’t work backwards from the data — work forwards from the docs. And if the docs are wrong you should submit a ticket and wait for it to be fixed (or at the very, very least, make sure your workaround deals with both the documented expectation and the actual incorrect return value).

In conclusion

Just like a child, it takes a village to raise a good, decent, hard working API.

Data for nothing and bytes for free is a freemium service, meaning that our awesome blogging platform is provided for free to everyone, and we make money by selling upgrades. We process thousands of user purchases each week and you might expect that we know a lot about our customers. The truth is, we are still learning. In this post, we will give you some insights into how we try to understand the needs and behaviors of users who buy upgrades.

We know there are many kinds of users and sites on To understand the needs of users who purchase upgrades, one would naturally analyze their content consumption and creation patterns. After all, those two things should tell us everything about our users, right?

Somewhat surprisingly, the median weekly number of posts or pages a user creates, and the median weekly number of likes and comments a user receives is zero! And I’m not talking about dormant users. These are our paying customers. There are lots of reasons for this, like static sites that don’t need to change very often, or blogs with a lower frequencies than weekly. But it doesn’t give us much data to work with.  Well, let’s start with something that IS known about every user: their registration date.

Thousands of users register daily on What does the day of the week on which the user registered with us say about their purchasing preferences? Is it possible that users who register during the week are more work-oriented, and users who register during weekends are more hobby oriented? To test this question, we’ll look at purchases that were made in our online store between March and September 2013.

We’ll divide the purchasing users in two groups: those who registered between Monday and Friday (let’s call them “workweek users”) and those who registered during Saturday and Sunday (let’s call them “weekend users”).

Side note: To the first approximation, we use registration GMT time to label a user as “registered on weekend” or “registered during the workweek”. We also ignore weekend differences that exist between the different countries. These are non-trivial approximations that make the analysis simpler and do not invalidate the answer to our question.

To examine the purchasing patterns of these groups let’s calculate the fraction of products purchased. For example: the most prevalent products in both categories were [domain mapping and registration]( These two products, that are usually bought together, are responsible for about 35% of upgrades bought by our workweek and weekend users. Let us now continue this comparison using a graph:


What do we learn from this comparison? Almost nothing. Which is not surprising, as purchasing distribution pattern is mostly determined by factors such as user preferences, demand, price etc.

Let’s look for more subtle differences. We’ll use a technique known as a Bland / Altman Plot. These British statisticians noted that plotting one value versus another implies that the one on the X axis is the cause and the one on the Y axis is the result. An alternative implication is that the X axis represents the “correct value”. None of these is correct in our case. We are interested in understanding the agreement (disagreement, to be more precise) between two similar measurements, when none of the two is superior over another. Thus, instead of plotting the two closely correlated metrics (purchase fractions in our case), we should plot their average values on the X axis and their difference on the Y axis. In this domain, higher X axis values designate more prevalent products, positive Y values designate preference towards the working days and negative Y values designate preference towards the weekend. This is what we get after transferring the fractions to logarithm domain:


Now things become interesting. Let us take a look at some of the individual points:


As I have already mentioned, domain mapping and registration are the most popular products. Not surprisingly, these products are equally liked by weekend and working week users. Recall our initial intuition that users who register during weekends will be more hobby-oriented and users that register during the week will be more job oriented. We now have some data that supports this intuition. Of all the products, private registration, followed by space upgrades have the strongest bias towards weekend users. Indeed, one would expect personal users to care about their privacy much more than corporate ones. Being more cost-sensitive, personal users are more likely to purchase space upgrade and not one of plans. The opposite side of the division line makes sense too: blocking ads is the cheapest option to differentiate a workplace site, followed by custom design. These two options are included in all our premium plans, but I can understand how a really small business would prefer buying some individual options.

Another note: If you are worried about statistical significance of this analysis, you are completely right. I don’t show this here, but exactly the same picture appears when we analyze data from different time periods.

So what?

As an app developer, you will at some point be frustrated about how little you know about your customers. Don’t give up! Start with the small things that you know. Things such as day of the week, geographical location and browser version may shed useful light and you can build out a picture from there, adding to it bit by bit. Having such information is like gardening: it sounds like a lot of work, but you might be surprised at what you can get from a little investment of time. With determination (asking lots of questions) and creativity (looking at a problem from new angles, starting with information you already have) and the right tools in your hands, you can learn something about your users and grow your garden of understanding.

OAuth2 Global Scope Tokens

The REST API has enabled developers to create rich applications to interact with blogs hosted on or hosted elsewhere when used with the Jetpack plugin. Until now, it’s only been possible to request an authorization token for a single blog at a time, but we’re happy to announce that this limitation has been lifted. Starting today, you can request access to all sites to which a user has administrative access by using the global scope option with our existing OAuth2 authentication process.

To use the new global scope, redirect your users to the OAuth2 authorization endpoint below to request access to all of the user’s sites:

The user will be presented with an improved authorization screen to more clearly reflect the permissions being granted to your application, as seen in the screenshot below.


You can learn more about the OAuth2 authentication flow at our detailed support article.

If the user chooses to grant you access to all of their sites, you will receive a token which includes a scope value of “global”.

    "access_token": "YOUR_API_TOKEN",
    "token_type": "bearer",
    "scope": "global",
    "blog_id": 0,
    "blog_url": null

Once you’ve received your access token, you can view all of the user’s sites by making a request to the /me/sites endpoint.

It’s important to consider whether or not your application needs access to all of a user’s sites or if working with a single blog at a time is sufficient. As you might expect, users will tend to be more cautious when granting access to all of their sites to an unfamiliar application.

We hope that this new feature will enable you to build more powerful applications where it’s useful to manage more than one site to which a user has access. If you have any questions, leave a comment below or use our contact form to reach us directly.

Authentication improvements for testing your apps

We’ve just made it easier for developers to authenticate and test API calls with their own applications.

As the client owner, you can now authenticate with the password grant_type, allowing you to skip the authorization step of authenticating, and logging in with your username and password. You can also gain the global scope so that you no longer need to request authentication for each blog you wish to test your code with.

This is especially useful to contributors of the WordPress Android and iOS apps, which previously required special whitelisting on our part.

Here’s an example of how you can get started with using both these features:

Note that if you are using 2-step authentication (highly recommended) you will need to create an application password to be able to use the password grant_type.

$curl = curl_init( "" );
curl_setopt( $curl, CURLOPT_POST, true );
curl_setopt( $curl, CURLOPT_POSTFIELDS, array(
    'client_id' => your_client_id,
    'client_secret' => your_client_secret_key,
    'grant_type' => 'password'
    'username' => your_wpcom_username,
    'password' => your_wpcom_password,
) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1);
$auth = curl_exec( $curl );
$auth = json_decode($auth);
$access_key = $auth->access_token;

As noted above, these are only available to you as the owner of the application, and not to any other user. This is meant for testing purposes only.

You can review existing authentication methods here.

If you have any questions, please drop them in the comments or use our contact form to reach us.

REST Development Console — now open source!

For developers working with the REST API, the browser-based API console is an essential debugging tool. It allows you to test your API queries and interactively explore the results (or errors) that the API returns.

REST API console - exploring results

It also puts the documentation at your fingertips and allows you to build a custom query right from any method’s description.

REST API console - building a query

Like the REST API itself, this tool works for any blog on and for any self-hosted WordPress install using Jetpack.

With the addition of implicit OAuth, we’ve released an open-source version of the API console that you can run yourself.

First, you’ll want to create a application (or modify an existing one) and make sure to set the Javascript Origins option. This should be the fully-qualified URL (including http:// or https:// ) of the site you’ll be running the API console on. To run it locally, just use “http://localhost”.

REST API console - JS origins setting

Then, just head on over to the GitHub repository, clone your own copy, and put your application’s info in the file config.json.

Screen Shot 2014-06-10 at 5.23.59 PM

When you’re running the console locally, you can authenticate by clicking on the box in the lower-right corner.

dev console - auth button

Once you’re linked to a blog, the blog’s ID will be shown in the lower right. You can click on it to change which blog you’re working with.

Important note: When you’ve connected to a blog, the console is hooked up to the live database — any changes you make will be reflected on that blog! You might want to create a test blog if you’re planning to make any requests that will modify content.

The REST API console is located at

If you’re using the API, we’d love to hear what you think! Have you used the development console? What’s great (or not so great) about it?

Meet Sulfur — a Media Manager App Built in JavaScript

Since Automattic is a distributed company and a lot of us work from home, we hold meetups to get face-to-face interaction. The whole company meets up once a year and individual teams get together more often. One component of those meetups is a “meetup project” that we all work on together.

The team I lead — “Team I/O*” — just finished a lovely week in Reykjavik, Iceland. Our team is responsible for partnerships and our APIs.

We spent the first day releasing better JavaScript support for our APIs. After that we decided to make an example app, mainly focusing on the new CORS support and implicit OAuth system.

We decided to build a media manager purely in the browser. We picked a codename and Sulfur was born.

Update: Check out the live demo!

Screen Shot 2014-05-20 at 5.18.13 PM

Sulfur is an app built using Backbone, Underscore.js, Plupload, jQuery, MomentJS, Bootstrap, RequireJS, and the JSON REST API.

It shows how you can use Implicit OAuth to do authentication without a server component. It also provides examples for using the API with Backbone and third party libraries like plupload for uploading media.

Sulfur allows you to upload images, view your entire media library contents, view meta data, and delete images. All the code is open source. Check out Sulfur on GitHub.

We learned a lot while building the app and hope to use that knowledge to improve our APIs both for internal and external use.

Screen Shot 2014-05-20 at 9.11.02 PM

Let us know what you think in the comments!

*Named after one of the moons of Jupiter and our love of APIs (input/output)