SkillAgentSearch skills...

Pyxero

Python API for accessing the REST API of the Xero accounting tool.

Install / Use

/learn @freakboy3742/Pyxero
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

PyXero

Python Versions PyPI Version Maturity BSD License Build Status

PyXero is a Python API for accessing the REST API provided by the Xero accounting tool. It allows access to both Public, Private and Partner applications.

Quickstart:

Install this library using the python package manager:

pip install pyxero

Using OAuth2 Credentials

OAuth2 is an open standard authorization protocol that allows users to provide specific permissions to apps that want to use their account. OAuth2 authentication is performed using tokens that are obtained using an API; these tokens are then provided with each subsequent request.

OAuth2 tokens have a 30 minute expiry, but can be swapped for a new token at any time. Xero documentation on the OAuth2 process can be found here. The procedure for creating and authenticating credentials is as follows (with a Django example at the end):

  1. Register your app with Xero, using a redirect URI which will be served by your app in order to complete the authorisation e.g. https://mysite.com/oauth/xero/callback/. See step 3 for an example of what your app should do. Generate a Client Secret, then store it and the Client Id somewhere that your app can access them, such as a config file.

  2. Construct an OAuth2Credentials instance using the details from the first step.

    >>> from xero.auth import OAuth2Credentials
    >>>
    >>> credentials = OAuth2Credentials(client_id, client_secret,
    >>>                                 callback_uri=callback_uri)
    

    If necessary pass in a list of scopes to define the scopes required by your app. E.g. if write access is required to transactions and payroll employees:

    >>> from xero.constants import XeroScopes
    >>>
    >>> my_scope = [XeroScopes.ACCOUNTING_TRANSACTIONS,
    >>>             XeroScopes.PAYROLL_EMPLOYEES]
    >>> credentials = OAuth2Credentials(client_id, client_secret, scope=my_scope
    >>>                                 callback_uri=callback_uri)
    

    The default scopes are ['offline_access', 'accounting.transactions.read', 'accounting.contacts.read']. offline_access is required in order for tokens to be refreshable. For more details on scopes see Xero's documentation.

  3. Generate a Xero authorisation url which the user can visit to complete authorisation. Then store the state of the credentials object and redirect the user to the url in their browser.

    >>> authorisation_url = credentials.generate_url()
    >>>
    >>> # Now store credentials.state somewhere accessible, e.g a cache
    >>> mycache['xero_creds'] = credentials.state
    >>>
    >>> # then redirect the user to authorisation_url
    ...
    

    The callback URI should be the redirect URI you used in step 1.

  4. After authorization the user will be redirected from Xero to the callback URI provided in step 1, along with a querystring containing the authentication secret. When your app processes this request, it should pass the full URI including querystring to verify():

    >>> # Recreate the credentials object
    >>> credentials = OAuth2Credentials(**mycache['xero_creds'])
    >>>
    >>> # Get the full redirect uri from the request including querystring
    >>> # e.g. request_uri = 'https://mysite.com/oauth/xero/callback/?code=0123456789&scope=openid%20profile&state=87784234sdf5ds8ad546a8sd545ss6'
    >>>
    >>> credentials.verify(request_uri)
    

    A token will be fetched from Xero and saved as credentials.token. If the credentials object needs to be created again either dump the whole object using:

    >>> cred_state = credentials.state
    >>> ...
    >>> new_creds = OAuth2Credentials(**cred_state)
    

    or just use the client_id, client_secret and token (and optionally scopes and tenant_id):

    >>> token = credentials.token
    >>> ...
    >>> new_creds = OAuth2Credentials(client_id, client_secret, token=token)
    
  5. Now the credentials may be used to authorize a Xero session. As OAuth2 allows authentication for multiple Xero Organisations, it is necessary to set the tenant_id against which the xero client's queries will run.

    >>> from xero import Xero
    >>> # Use the first xero organisation (tenant) permitted
    >>> credentials.set_default_tenant()
    >>> xero = Xero(credentials)
    >>> xero.contacts.all()
    >>> ...
    

    If the scopes supplied in Step 2 did not require access to organisations (e.g. when only requesting scopes for single sign) it will not be possible to make requests with the Xero API and set_default_tenant() will raise an exception.

    To pick from multiple possible Xero organisations the tenant_id may be set explicitly:

    >>> tenants = credentials.get_tenants()
    >>> credentials.tenant_id = tenants[1]['tenantId']
    >>> xero = Xero(credentials)
    

    OAuth2Credentials.__init__() accepts tenant_id as a keyword argument.

  6. When using the API over an extended period, you will need to exchange tokens when they expire. If a refresh token is available, it can be used to generate a new token:

    >>> if credentials.expired():
    >>>     credentials.refresh()
    >>>     # Then store the new credentials or token somewhere for future use:
    >>>     cred_state = credentials.state
    >>>     # or
    >>>     new_token = credentials.token
    
    **Important**: ``credentials.state`` changes after a token swap. Be sure to
    persist the new state.
    
    

Django OAuth2 App Example

This example shows authorisation, automatic token refreshing and API use in a Django app which has read/write access to contacts and transactions. If the cache used is cleared on server restart, the token will be lost and verification will have to take place again.

from django.http import HttpResponseRedirect
from django.core.cache import caches

from xero import Xero
from xero.auth import OAuth2Credentials
from xero.constants import XeroScopes

def start_xero_auth_view(request):
   # Get client_id, client_secret from config file or settings then
   credentials = OAuth2Credentials(
       client_id, client_secret, callback_uri=callback_uri,
       scope=[XeroScopes.OFFLINE_ACCESS, XeroScopes.ACCOUNTING_CONTACTS,
              XeroScopes.ACCOUNTING_TRANSACTIONS]
   )
   authorization_url = credentials.generate_url()
   caches['mycache'].set('xero_creds', credentials.state)
   return HttpResponseRedirect(authorization_url)

def process_callback_view(request):
   cred_state = caches['mycache'].get('xero_creds')
   credentials = OAuth2Credentials(**cred_state)
   auth_secret = request.build_absolute_uri()
   credentials.verify(auth_secret)
   credentials.set_default_tenant()
   caches['mycache'].set('xero_creds', credentials.state)

def some_view_which_calls_xero(request):
   cred_state = caches['mycache'].get('xero_creds')
   credentials = OAuth2Credentials(**cred_state)
   if credentials.expired():
       credentials.refresh()
       caches['mycache'].set('xero_creds', credentials.state)
   xero = Xero(credentials)

   contacts = xero.contacts.all()
   ...

Using PKCE Credentials

PKCE is an alternative flow for providing authentication via OAuth2. It works largely the same as the standard OAuth2 mechanism, but unlike the normal flow is designed to work with applications which cannot keep private keys secure, such as desktop, mobile or single page apps where such secrets could be extracted. A client ID is still required.

As elsewhere, OAuth2 tokens have a 30 minute expiry, but can be only swapped for a new token if the offline_access scope is requested.

Xero documentation on the PKCE flow can be found here. The procedure for creating and authenticating credentials is as follows (with a CLI example at the end):

  1. Register your app with Xero, using a redirect URI which will be served by your app in order to complete the authorisation e.g. http://localhost:<port>/callback/. You can chose any port, and can pass it to the credentials object on construction, allow with the the Client Id you are provided with.

  2. Construct an OAuth2Credentials instance using the details from the first step.

    >>> from xero.auth import OAuth2Credentials
    >>>
    >>> credentials = OAuth2PKCECredentials(client_id,   port=my_port)
    

    If necessary, pass in a list of scopes to define the scopes required by your app. E.g. if write access is required to transactions and payroll employees:

    >>> from xero.constants import XeroScopes
    >>>
    >>> my_scope = [XeroScopes.ACCOUNTING_TRANSACTIONS,
    >>>             XeroScopes.PAYROLL_EMPLOYEES]
    >>> credentials = OAuth2Credentials(client_id, scope=my_scope
    >>>                                 port=my_port)
    

    The default scopes are ['offline_access', 'accounting.transactions.read', 'accounting.contacts.read']. offline_access is required in order for tokens to

Related Skills

View on GitHub
GitHub Stars282
CategoryFinance
Updated1d ago
Forks210

Languages

Python

Security Score

95/100

Audited on Apr 2, 2026

No findings