Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > API Authentication >

Need persistent, long-term API access - getting a tenant ID after refreshing a token doesn't work?

Started by Adam Thomas -   in API Authentication

I'm building a system that needs to import orders (invoices) from a web store into Xero. It needs to be up continuously and function without intervention.

So far, I'm using this process to connect.

### One-time task

* Head to the OAuth user confirmation login URL.
* User (me) clicks confirm.
* Copy the user code out of the redirected URL.
* Use the user code to retrieve an access token.
* Use the access token to retrieve a tenant ID.

### On each order import

* Refresh the access token. Get a new refresh token *and a new access token* (this behaviour does not seem to be documented).
* Try to use the new access token to retrieve another tenant ID. This doesn't seem to work - the request succeeds, but I get no tenants back in the response. This also isn't documented.
* Attempt to POST to `/Invoices`. This fails with an AuthenticationUnsuccessful response.

I've tried:

* Using the original access token (didn't work)
* Using the original tenant ID (also didn't work)

It seems that a tenant ID is tied to a specific access token, which means that when the refresh operation returns a slightly different access token, the tenant ID becomes invalid. Is this normal behaviour? Am I supposed to use some other value instead of the `access_token` in the authentication response, one which might remain consistent across refreshes? Is there a more robust way of long-term authentication available, like the Oauth1 private apps?
Access tokens are specific to the user & app - not the tenant - but the user needs to specifically authorise each tenant for which they want to make API requests.

You'll be calling the /connections endpoint In your step "Use the access token to retrieve a tenant ID" - the response from that endpoint will include the list of all the tenants that the user has authorised to make requests. If you're only getting one tenant back in that response, you'll need to go through the authorise flow again, and choose another tenant (i.e. Xero organisation) to authorise.

As a result, your step "Try to use the new access token to retrieve another tenant ID" won't be necessary, because you'll get all the available tenant ids at once in your response from /connections.

Russell Dear (Xero Staff)  

As it was, I was getting one tenant back from the initial connection, and then zero tenants after refreshing the access token.

Fortunately, I think I have a solution - I posted the same question to support and they told me to add the `offline_access` scope to the initial login request. As far as I can tell, that seems to have solved the problem, and the tenant ID now persists beyond the first half hour. Hope that helps anyone else reading :)


Adam Thomas  

EDIT: Disregard my comment below. It appears I was missing "accounting.settings" and "accounting.transactions" in my scope, which can be seen in the sample project.


I'm currently getting no tenants off the initial connection and i have the "offline_access" scope in my configuration that I pass in. Based off of Russell's explanation, I need to authorise specific tenants so they show up? Would someone be able to link me to a resource or give an explanation that elaborates more on this?

Matthew Guillemette  

Did you get tenant_id in the login api response?

I am trying to access from python code, added offline_access scope, but still I am not getting tenant_id in response. However, I am getting marketplace_billing in the response instead od offline_scope.

Would someone pls help me here.


Rajal Bhatt