Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > API Authentication >

Xero API (Private Application) access from JavaScript (Google Apps)

Started by Rob Bishop -   in API Authentication

Just put together a Google Apps Script (JavaScript) that will sync data from my tills with Xero as a scheduled task. Has anyone else got a JavaScript solution as although this works the rsa-sha1 sign method runs slow in Google (not locally though) and the script may time out. My solution is based on http://www9.atwiki.jp/kurushima/pub/jsrsa/
Hi Rob,
I'm very interested how did you construct your API call inside GoogleApps script.
I have included all rsa libraries (from link of yours) and, on my surprise, it actually correctly signs provided message :)
But, not sure what to do next, what do I actually need to sign? I have set-up private application on Xero, and received key and secret.

Thank you very much,
I appreciate you help!

Matija Svoren  

Hi Matija,

Happy to share what I have, however I abandoned this method as although I could get it work initially (albeit very slowly) I started to receive the 'Exceeded maximum instruction count' error. The RSA signing method must be pretty labour intensive. There is some help on this here http://code.google.com/googleapps/appsscript/guide_troubleshooting.html, but I never followed up on it. What we really need is for Google to add an RSA signing method to their Apps Script API.

I did manage to achieve my goal of syncing a Google Spreadsheet with Xero using Google Apps Scripting but I ended up using a Xero Public application (which requires interactive sign-on and limits you to a 30 minute access token). I am happy to send that on if you wish. As for the private application this is what I did, hopefully you will have more success than me.

1) Add all the script resources referenced by the web page http://www9.atwiki.jp/kurushima/pub/jsrsa/sample-rsasign.html into a Google apps script project. Remove all occurrences of browser Api methods (navigator, alert, etc)

2) Add the script found in the zip file http://www.kevlindev.com/utilities/base64/base64.zip to provide base64 encoding functionality. Although there is a method for base64 encoding in the RSA script files these seem to work only with binary strings and not binary arrays. Check out http://www.kevlindev.com/utilities/index.htm for information.

3) Add the following user properties:
i) pemKey - The private key as a string, starts with -----BEGIN RSA PRIVATE KEY-----
ii) consumerKey - provided by Xero and associated with a specific Private application
iii) userAgent - The name of the Private application in Xero

4) This is a far as I got, it calls the Organisation endpoint as a get request.

Rob Bishop  

Hi Rob,
This is excellent! Thank you very much, I managed to do GET, and POST as well.


Matija Svoren  

Hi Rob & Matija,

I've also working on the same task, Syncing data from Google Spreadsheet to Xero. Followed the steps listed down by Rob.

When I run the script, am getting the below error:(which means that this class not loaded properly)
ReferenceError: "RSAKey" is not defined. (line 31, file "Code")

I've 13 files in total in my library which are referenced in http://www9.atwiki.jp/kurushima/pub/jsrsa/sample-rsasign.html

I might be missing a small step here, can you please help to move from here.


Pavan Kumar  

Thanks in advance

Pavan Kumar  


I am also working on the project that Pavan mentioned above, is their anybody out their that can help us


Zane Tootell  

How to set "If-Modified-Since" in google app script request

Bharat Kasodariya  

Hi Rob,

I'm looking to be able to create invoices from a Google Script. Could you send me your instructions for connecting using a Public application as I think I'm going to need to go down that route - being limited to 2 private applications per company could cause us problems :)

Thanks in advance


Jon Boulter  

The hard part of oauth seems the encryption.
This link explains what need to be done in a general way when using oauth1. The private demo with that tutorial should give the key to generate the public one.

The code from Rob is working for me. Look at his `14 Oct 2011` post.
The lib that you import need to be put in the good order (have a look at the comments at the top of each libs). => it's the solution to the "RSAKey" is not defined.

Thibault Deheurles  

Updated to use single file to include missing RSAKey function and updated base64 encoding.


James Ryan  

James Ryan, you said it's been updated to use a single file, but which one is it on the http://kjur.github.io/jsrsasign/ site - I just seem to get sucked into including more and more? Thanks.

Andrew Roberts  

I'm using jsrsasign-5.0.x-all-min.js

The RSA signing is still very slow; takes about 10 seconds to sign a request.

I forgot to mention - you will need to remove references to browser and window etc. They will pop up as errors in Google Apps Script. Change them to null or false or whatever is required to make the errors stop.

Also see http://nouncer.com/oauth/signature.html for an explanation of the OAuth 1.0 spec. The authentication Xero uses for private applications makes signing the requests correctly quite tricky, particularly the order of parameters, and non standard percent encoding.

James Ryan  

James, you star! It worked. I copied jsrsasign-5.0.x-all-min.js into it's own script file and added:

var navigator = {appName: 'none'}
var window = null

to get rid of a couple of errors.

I'm sure future travellers on this path would appreciate the addition of this file name to your Gist!

This is the required file on Github: https://github.com/kjur/jsrsasign/blob/master/jsrsasign-5.0.1-all-min.js

Andrew Roberts  

Check out this script: https://github.com/rakesh456/xero-api-apps-script. An GSheet script for public, private and partner apps.

And you can use https://github.com/kjur/jsrsasign/blob/master/jsrsasign-5.0.1-all-min.js instead of copying in all those indivdual files.

Andrew Roberts  

Hi All,

I'd like to enter this discussion. Andrew Roberts mentioned, in another thread...


...that he has been having trouble with the dateTime calls. I had a similar problem for a moment, not sure if it is the same issue. I would get the following error when running the "Manual Upload Invoices" script from the XERO menu in the spreadsheet:

Cannot find method formatDate(string,string,string)

I stopped the error by properly formatting the date in the "Invoices Upload" sheet.

I have some unrelated questions. i copied and pasted the Xero.gs and Code.gs files to my apps script project. How are you handling the rsa folder? This needs to be included in the script? Do you just copy and paste each file in that rsa folder into a separate script file within the project?

Eathan Janney  

This is the required file on Github that contains all of the RSA stuff in one file: https://github.com/kjur/jsrsasign/blob/master/jsrsasign-5.0.1-all-min.js.

Add the lines below to get rid of a couple of errors.

var navigator = {appName: 'none'}
var window = null

Andrew Roberts  

Does anybody know what the equivalent of

UrlFetchApp.fetch("https://api.xero.com/api.xro/2.0/Organisation", options)

if using jQuery $.ajax(...) ?

The reverse of this:

Specifically, I am creating a Private Application that is accessible from an Office Add-In so I only have jQuery. The private key, consumer key and consumer secret will be on the local machine so there is no real client-side exposure traditionally associated with having your private key hardcoded into the HTML being delivered to the browser


Chris Go  

If anyone ends up here in future I put together a 'just works' solution on Github based on the discussion above:



Callum Silcock  

Hi Callum, HAve you had any luck with passing queries/parameters like date, type etc? I have no issue with the page query but on everything else I still get a 200 response code but the filters have no effect.

Richard ward  

Hi Richard, were you able to get the parameters on a get working? I am having a simmilar issue. The report api endpoint authenticates and works with no parameters. However when I try to add parameters I get an authentication failed response.

Let me know if you were able to find a solution!

Danyal Khan  

@Danyal, This was a while back but I think it had something to do with how you encode the query string. Take a look at connect() in https://github.com/fdworks/Xero-GAS/blob/master/Api_.gs

Andrew Roberts  

Thanks Andrew it worked!

Just in case someone comes back here.

The solution that worked for me is to encode the parameter in the signature base:

var signatureBase = "GET" + "&" + encodeURIComponent(URL) + "&" + encodeURIComponent("oauth_consumer_key=" + CONSUMER_KEY + "&oauth_nonce=" + oauth_nonce + "&oauth_signature_method=RSA-SHA1&oauth_timestamp=" + oauth_timestamp + "&oauth_token=" + CONSUMER_KEY + "&oauth_version=1.0" + '&trackingCategoryID=abc123&trackingOptionID=123abc');

And also add it to the fetch url:

UrlFetchApp.fetch(URL + '?trackingCategoryID=abc123&trackingOptionID=123abc', options);

This should work for other parameters as well.

Danyal Khan  

In case it helps someone else: we had a problem with GAS timing out because jsrsasign was taking 10 seconds or more for RSA-SHA1 signing when running client-side. So we created a Google Cloud Function to run the signing, which reduced the signing time to less than 2 seconds. Still slow, but no more timeouts.

Jeremy Nicholls