OAuth 2.0 App Partner Migration Guide

This guide is for developers migrating an OAuth 1.0a partner app to OAuth 2.0. It will allow you to seamlessly move your existing connections to OAuth 2.0 without any disruption to customers.

While the migration process is quite straightforward, there is a fundamental change to how things work in OAuth 2.0 that you’ll need to carefully plan for:

User-based OAuth

Our OAuth 2.0 implementation issues access tokens on a per-user basis. This is a big change from OAuth1.0a where access tokens were issued for an individual tenant (organisation or practice). Users can still select which tenants an app can access but that will be handled separately to the token.


Decoupling the access token from the tenant is a significant change that opens up a range of benefits:

  • The ability to use Xero as a single sign-on provider for your app.
  • The ability to leverage OpenID Connect for smoother onboarding to your app from the Xero marketplace.
  • The ability for users to connect multiple Xero tenants (organisations or practices) to your app in a single authorisation flow.

Changes to how you store tokens

The data you need to store for Xero OAuth 2.0 connections will be very similar to what you’re currently storing for OAuth1.0a. Instead of storing an oauth_token you’ll have an access_token and instead of having an oauth_session_handle you’ll have a refresh_token.

However, in the case where the same user has granted access to multiple orgs or practices you will use the same access and refresh tokens for each of those “connections”. A simple example might look like:


Which you may want to normalise to something like...

How to migrate your app

Step one: Create credentials

To generate a client id and client secret for your app you’ll need to go to My Apps and open your existing partner app. In the OAuth2.0 credentials section add at least one redirect URI and click save.

Note: In OAuth 1.0a you only needed to provide the callback domain; in OAuth 2.0 you need to provide the full callback URI.

You now have your client id and secret for making OAuth 2.0 requests.

Step two: Build your integration

Once you have your credentials you can start building your OAuth 2.0 integration. We recommend you use one of our new OAuth 2.0 SDKs which will be maintained and updated by Xero. You’re welcome to fork your current SDK and add any standard OAuth 2.0 or OIDC library but these will not be actively maintained by Xero in future.

Read the documentation on our OAuth 2.0 flow to see how auth will differ from your current implementation. Make sure you familiarise yourself with the new scopes in OAuth 2.0 and work out which ones are required.

Once you have OAuth 2.0 working in your app we’d recommend putting new connections onto OAuth 2.0 to make sure everything is working as expected. Your existing OAuth 1.0a connections will continue to work as normal and all connections will count toward your active connections for the partner program.

Step three: Migrate existing connections

When you’re confident that your OAuth 2.0 implementation is running smoothly, you can swap your existing OAuth 1.0a access tokens for OAuth 2.0 access and refresh tokens. This allows you to seamlessly move your existing customers across without them having to re-consent.

We’ve tried to make this process as simple as possible. It's a simple POST request with the OAuth 1.0a authorization header. Your current OAuth 1.0a SDK is probably already generating this header for you. Provide your app’s OAuth 2.0 credentials in the request body and a successful response will include an OAuth 2.0 access token, refresh token and xero tenant id in the response.

The migrate endpoint

Required elements in a migration request:

scope The scopes required for your integration. It must include the offline_access scope and at least one other scope.

It must not include any OpenID scopes. These must be explicitly consented by the user separately (e.g. as part of a Sign in with Xero flow).
redirect_uri Must match a redirect URI saved against your app when you created your OAuth 2.0 credentials.
client_id Your client id
client_secret Your client secret
Content-Type: application/json
Authorization: OAuth oauth_consumer_key="your_consumer_key", oauth_token="your_access_token", 
    oauth_signature_method="RSA-SHA1", oauth_signature="your_signature", oauth_timestamp="1456175435", 
    oauth_nonce="83fd12eb-f578-4403-bd55-247b66efa11a", oauth_version="1.0"
Body: {
    "scope":"your_oauth_2_scopes + offline_access",

Note: The request must be in JSON. XML is not supported.

A successful response includes:

access_token The bearer token used to make calls against the API
refresh_token The refresh token used to generate a new access token when the current one expires (30 mins)
expires_in The time (in seconds) until the access token expires
token_type This will always be “Bearer”
xero_tenant_id The identifier for the org that has been migrated

When you receive the response we recommend you decode the access token (a JWT) to get the xero_userid. If you have an existing access token and refresh token for that user (e.g. from a previous organisation you’ve migrated) you should replace the existing tokens and append the xero_tenant_id to the list of authorised tenants for that user.

Migration rate limit

The migration endpoint has a rate limit of 5000 requests per app per minute, separate from the rate limits across the other endpoints.

OpenID Connect and Sign in with Xero

The OpenID Connect identity layer is a new feature of OAuth 2.0 and consent to access a user’s profile information can’t be migrated from OAuth 1.0a.

A user will need to consent access to their profile information the first time they go through a Sign in with Xero flow and the scopes will be appended to their consent at that time.

Migrating Xero HQ connections

When migrating connections for Xero HQ you need to add a ?tenantType=PRACTICE parameter to the request e.g.


When migrating these connections you should only request Xero HQ scopes. All the other details are the same as migrating organisation connections.


Can I re-run my token migration if I need to?


Can I still use my OAuth 1.0a access tokens after they’ve been migrated?

Yes, if something goes wrong you can fall back to using your OAuth1.0a tokens (assuming they’re still valid).

Is there a way to figure out which Xero organisations an access token can be used with?

Yes - you can make a GET request to the /connections endpoint, supplying the access token as a bearer token in the Authorization header, to retrieve the set of tenants for which the access token is valid.

Sample code

To see the migration flow in action, check out our sample app.