Package: pyfortnox
pyfortnoxFortnox API V3 library client for PythonInstallationpyfortnox package can be installed either viapiporeasy_install:$ pip install --upgrade pyfortnoxor$ easy_install --upgrade pyfortnoxYou can install from the source code as well. First clone the repo and
then execute:$ python setup.py installAfter installing, importpyfortnoxpackage:import fortnoxUsageimport fortnoxBuild a clientUsing this api without authentication gives an error# Then we instantiate a client (as shown below)client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')Client OptionsThe following options are available while instantiating a client:access_token: Personal access tokenclient_secret: Private/public integration app's client secretbase_url: Base url for the apitimeout: Request timeoutverbose: Verbose/debug modeArchitectureThe library follows few architectural principles you should understand
before digging deeper.Interactions with resources are done via
service objects.Service objects are exposed as properties on client
instances.Service objects expose resource-oriented actions.Actions return dictionaries that support attribute-style access, a la
JavaScript (thanks to Bunch and it's form Munch).For example, to interact with projects API you will usefortnox.ProjectService, which you can get if you call:client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')client.projects# fortnox.ProjectServiceTo retrieve list of resources and use filtering you will calllist()method:client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')client.projects.list(organization_id=google.id,hot=True)# list(dict|Munch)or simplyclient.projects.list()To find custom field by name and its value pass kwargs as an argument:client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')client.projects.list(**{'ProjectNumber':1})To find a resource by its unique identifier useretrieve()method:client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')client.projects.retrieve(id=1)When you'd like to create a resource, or update it's attributes you want
to use eithercreate()orupdate()methods. For example if you
want to create a new project you will call:client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')project=client.projects.create(Description='Website design',Status='ONGOING')project.ProjectNumber=1project.Status='ONGOING'project.Description='Website redesign'client.projects.update(project.ProjectNumber,StartDate='2014-02-28')To destroy a resource usedestroy()method:client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')client.projects.destroy(project.ProjectNumber)There other non-CRUD operations supported as well. Please contact
corresponding service files for in-depth documentation.Full example# Obtain an access token using a new authorization code. This access token will# then be used for any further API calls.client=fortnox.Client(authorization_code='<YOUR_APP_INTEGRATION_AUTHORIZATION_CODE>',client_secret='<YOUR_APPS_CLIENT_SECRET>')obtained_token=client.token.access_token()access_token=obtained_token.AccessTokenHandling ExceptionsWhen you instantiate a client or make any request via service objects,
exceptions can be raised for multiple of reasons e.g. a network error,
an authentication error, an invalid param error etc.Sample below shows how to properly handle exceptions:try:# Instantiate a client.client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')project=client.projects.create(Description='Website design',Status='ONGOING')print(project)exceptfortnox.ConfigurationErrorase:#  Invalid client configuration optionpassexceptfortnox.ResourceErrorase:# Resource related errorprint('Http status = '+e.http_status)print('Request ID = '+e.logref)forerrorine.errors:print('field = '+error.field)print('code = '+error.code)print('message = '+error.message)print('details = '+error.details)exceptfortnox.RequestErrorase:# Invalid query parameters, authentication error etc.passexceptExceptionase:# Other kind of exceptioni, probably connectivity relatedpassSample below shows how to send files via inbox service with handled exceptions:try:# Instantiate a client.client=fortnox.Client(access_token='<YOUR_PERSONAL_ACCESS_TOKEN>',client_secret='<YOUR_APPS_CLIENT_SECRET>')fromioimportBytesIOfile=open('/your/local/file/path/voucher_file.jpeg','rb')buffered_file=BytesIO(file.read())file_name='voucher1.jpg'voucher_file=client.inbox.create(path='inbox_v',file=buffered_file,file_name=file_name)print(voucher_file)exceptfortnox.ConfigurationErrorase:#  Invalid client configuration optionpassexceptfortnox.ResourceErrorase:# Resource related errorprint('Http status = '+e.http_status)print('Request ID = '+e.logref)forerrorine.errors:print('field = '+error.field)print('code = '+error.code)print('message = '+error.message)print('details = '+error.details)exceptfortnox.RequestErrorase:# Invalid query parameters, authentication error etc.passexceptExceptionase:# Other kind of exceptioni, probably connectivity relatedpassResources and actionsDocumentation for every action can be found underfortnox/services/files.To know about available services, see Fortnox's Official Developer Documentationhttps://developer.fortnox.se/documentation/N.B. Below services are not implemented in the latest release of pyfortnox:Digital ReceiptWarehouse Custom Inbound DocumentsWarehouse Custom Outbound DocumentsWarehouse InformationWarehouse Item SummaryWarehouse Resource Specific FieldsTestsTo run all test suites:$ python setup.py testAnd to run a single suite:$ python setup.py test -s fortnox.test.test_associated_project_service.ProjectServiceTestsThanksI would like to give huge thanks to my wife, fellow colleagues, mentors and friends for
their continuous inspiration and supports to contribute to this package.pyfortnoxwas named frompythonic fortnoxand I was lucky to publish wrapper underpyfortnoxname.Thank You!LicenseMITBug ReportsReport hereContactMahmudul Hasan (ikhtiarcse10ruet@gmail.com)Powered By