OAuth2 is a protocol that allows applications to interact with blogs on WordPress.com and self-hosted WordPress sites running Jetpack. The primary goal of OAuth is to allow developers to interact with WordPress.com and Jetpack sites without requiring them to store sensitive credentials. Our implementation also allows users to manage their own connections.

If you are new to the world of OAuth, you can read more at http://oauth.net. If you are already familiar with OAuth, then all you really need to know about are the two authentication endpoints: the authorization endpoint and the token request endpoint. These endpoints are https://public-api.wordpress.com/oauth2/authorize and https://public-api.wordpress.com/oauth2/token

The same endpoints are used for WordPress.com blogs and Jetpack sites. Before you begin to develop an application, you will need a client id, redirect URI, and a client secret key. These details will be used to authenticate your application and verify that the API calls being made are valid. You can create an application or view details for your existing applications with our applications manager.

Receiving an Access Token

To act on a user’s behalf and make calls from our API you will need an access token. To get an access token you need to go through the access token flow and prompt the user to authorize your application to act on their behalf.

Access tokens can be requested per blog per user or as a global token per user. In addition to the global tokens, there are certain endpoints (e.g. likes and follows) where you can use a user’s token on any blog to act on their behalf.

To begin, you will need to send the user to the authorization endpoint. Here’s an example request:


Required parameters:

  • client_id should be set to your application’s client ID as found in the applications manager.
  • redirect_uri should be set to the URL that the user will be redirected back to after the request is authorized. The redirect_uri must match the one in the applications manager.
  • response_type can be “code” or “token”. “Code” should be used for server side applications where you can guarantee that secrets will be stored securely. These tokens do not expire. “Token” should be used for client-side applications. This is called “Implicit OAuth”.  Tokens currently last two weeks and users will need to authenticate with your app once the token expires. Tokens are returned via the hash/fragment of the URL.

Optional parameters:

  • blog  You may pass along a blog parameter (&blog=) with the URL or blog ID for a WordPress.com blog or Jetpack site. If you do not pass along a blog, or if the user does not have administrative access to manage the blog you passed along, then the user will be prompted to select the blog they are granting you access to.
  • scope, if specified, can be set as “global” or “auth”. If omitted, the authorization token will only grant you access to a single blog. You may request global scope (&scope=global) to access all blogs that the user has access to on WordPress.com, including any Jetpack blogs they have connected to their WordPress.com account. If you are specifying the scope as global then you should omit the blog parameter. The auth scope (&scope=auth) will grant you access to the /me endpoints only, and is primarily used for WordPress.com Connect.

Server / Code Authentication

The redirect to your application will include a code which you will need in the next step. If the user has denied access to your app, the redirect will include ?error=access_denied. Once the user has authorized the request, they will be redirected to the redirect_url. The request will look like the following: https://developer.wordpress.com/?code=cw9hk1xG9k

This is a time-limited code that your application can exchange for a full authorization token. To do this you will need to pass the code to the token endpoint by making a POST request to https://public-api.wordpress.com/oauth2/token.

$curl = curl_init( 'https://public-api.wordpress.com/oauth2/token' );
curl_setopt( $curl, CURLOPT_POST, true );
curl_setopt( $curl, CURLOPT_POSTFIELDS, array(
	'client_id' => your_client_id,
	'redirect_uri' => your_redirect_url,
	'client_secret' => your_client_secret_key,
	'code' => $_GET['code'], // The code from the previous request
	'grant_type' => 'authorization_code'
) );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1);
$auth = curl_exec( $curl );
$secret = json_decode($auth);
$access_key = $secret->access_token;

You are required to pass client_id, client_secret, and redirect_uri for web applications. These parameters have to match the details for your application, and the redirect_uri must match the redirect_uri used during the Authorize step (above). grant_type has to be set to “authorization_code”. code must match the code you received in the redirect. If everything works correctly and the user grants authorization, you will get back a JSON-encoded string containing the token and some basic information about the blog:

    "access_token": "YOUR_API_TOKEN",
    "blog_id": "blog ID",
    "blog_url": "blog url",
    "token_type": "bearer"

You now have an access token which should be stored securely with the blog ID and blog URL. This access token allows your application to act on the behalf of the user on this specific blog.

Testing an application as the client owner

As the client owner, you can authenticate with the password grant_type, allowing you to skip the authorization step of authenticating, instead logging in with your WordPress.com username and password. 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( 'https://public-api.wordpress.com/oauth2/token' );
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, this is only available to you as the owner of the application, and not to any other user. This is meant for testing purposes only.

Client/Implicit Oauth

Once the user authenticates their blog, they will be redirected back to your application. The token and user information will be included in the URL fragment.


This token will allow you to make authenticated client-side calls using CORS/AJAX requests. The token currently only lasts two weeks. Use the expires_in fragment to detect when you should prompt for a refresh.

Validating Tokens

It can be helpful to be able to validate the authenticity of a token, specifically that it belongs to your application and the user you are authenticating. This is especially necessary when sending a token over the wire (e.g. mobile application sending token as login credentials to an API). To verify a token, use the `/oauth/token-info` endpoint, passing in the `token` and your `client_id`:


If the token provided was not authorized for your application, the endpoint will return an error. If the token is valid, you will get a JSON-encoded string with the user ID and scope of the token:

    "client_id": "your client ID",
    "user_id": "user ID",
    "blog_id": "blog ID",
    "scope": "scope of the token"

Making an API call

Our API is JSON-based. You can view all of the available endpoints at our API documentation. You can also make API calls with our legacy XML-RPC API. In order to make an authenticated call to our APIs, you need to include your access token with the call. OAuth2 uses a BEARER token that is provided in an Authorization header.

$access_key = 'YOUR_API_TOKEN';
$curl = curl_init( 'https://public-api.wordpress.com/rest/v1/me/' );
curl_setopt( $curl, CURLOPT_HTTPHEADER, array( 'Authorization: Bearer ' . $access_key ) );
curl_exec( $curl );

The above example would return information about the authenticated user.

jQuery.ajax( {
    url: 'https://public-api.wordpress.com/rest/v1/sites/' + site_id + '/posts/new',
    type: 'POST',
    data: { content: 'testing test' },
    beforeSend : function( xhr ) {
        xhr.setRequestHeader( 'Authorization', 'BEARER ' + access_token );
    success: function( response ) {
        // response
} );

The above example would create a new post. You can make similar calls to the other available endpoints.