Electronic invoicing with Python
This tutorial builds two simple Python applications from scratch:
- Receive: connects and authenticates with the Invoicetronic API and downloads any new incoming invoices.
- Send: connects and authenticates with the Invoicetronic API and sends an invoice to the SDI.
Before continuing, make sure all the prerequisites below are met.
Prerequisites
We assume that these prerequisites are met:
- Python 3.9+ has been downloaded and installed
- pip is installed (comes with Python)
- You obtained an active API Key
- You registered with the Italian Revenue Service (needed for the live environment)
We use pip for dependency management, which is the de facto standard for modern Python.
Tip
For an optimal Python experience, consider using VS Code with the Python extension or PyCharm for a complete IDE.
Did you know?
The Python SDK supports type hints and Pydantic validation, providing runtime checks and better IDE autocomplete.
Receive
Create the app
The first step is to create the application directory:
Install the SDK
Install the Invoicetronic Python SDK:
Once that's done, open VS Code in the current directory:
Configure the SDK
Create a new file called index.py and add the following code:
import invoicetronic_sdk
from invoicetronic_sdk.rest import ApiException
# Configure the SDK
configuration = invoicetronic_sdk.Configuration(
username='YOUR TEST API KEY (starts with ik_test_)',
host='https://api.invoicetronic.com/v1'
)
As you can see, we configure the SDK by passing your test API Key (not the live one) and the API host. Notice how we use the username parameter to set the API Key.
API Key comes in pairs
When you create your account, you obtain a pair of API Keys. One is the test key for the API Sandbox, and the other is the live API's. You can tell the difference because the former starts with ik_test_, while the latter begins with ik_live_. In this tutorial, always use the test key.
Download invoices
We are ready to make a request. We want to download new vendor invoices that may be available from the SDI. Add these lines:
import base64
# Download unread invoices
with invoicetronic_sdk.ApiClient(configuration) as api_client:
receive_api = invoicetronic_sdk.ReceiveApi(api_client)
try:
inbound_invoices = receive_api.receive_get(
unread=True,
include_payload=True
)
print(f"Received {len(inbound_invoices)} invoices")
for invoice in inbound_invoices:
if invoice.encoding == 'Xml':
with open(invoice.file_name, 'w', encoding='utf-8') as f:
f.write(invoice.payload)
elif invoice.encoding == 'Base64':
with open(invoice.file_name, 'wb') as f:
f.write(base64.b64decode(invoice.payload))
print(f"Downloaded {invoice.file_name} from a vendor with VAT ID {invoice.prestatore}")
except ApiException as e:
print(f"Error: {e}")
Payload Inclusion
We set include_payload=True to retrieve the actual invoice content in the payload property. Without this parameter, the payload field would be None by default, which increases performance and reduces response size when you only need metadata.
In the terminal, run the application:
You should obtain an output similar to this one:
Received 3 invoices
Downloaded file1.xml from a vendor with VAT ID IT06157670966
Downloaded file2.xml.p7m from a vendor with VAT ID IT01280270057
Downloaded file3.xml.p7m from a vendor with VAT ID IT01280270057
The files are in the current directory, ready for you to inspect them.
Not receiving invoices in the live environment?
Ensure you registered with the Italian Revenue Service, which is a requirement for the live environment.
What we learned
In this example, we learned several things.
-
We must configure the SDK by creating a
Configurationinstance and passing username (API key) and host (API URL). -
We use the
withcontext manager to automatically handle API client closure. We instantiateApiClientpassing the configuration. -
We must instantiate a class representing the endpoint we want to work with. In this case, we leverage
ReceiveApito download incoming invoices, passing the API client. -
Endpoint classes like
ReceiveApioffer methods for interacting with their target entity. We callreceive_get()to retrieve invoices. Because we only want new, unread invoices, we passunread=True. We also passinclude_payload=Trueto retrieve the actual invoice content. -
Invoice objects expose attributes like
encoding,file_name, andpayload. The last one contains the invoice content, as plain text or Base64-encoded, as described byencoding.
Source Code on GitHub
The source code for this Quickstart is also available on GitHub.
Send
Create the app
The first step is to create the application directory:
Install the SDK
Install the Invoicetronic Python SDK:
Once that's done, open VS Code in the current directory:
Configure the SDK
Create a new file called index.py and add the following code:
import invoicetronic_sdk
from invoicetronic_sdk.rest import ApiException
from invoicetronic_sdk.models.send import Send
# Configure the SDK
configuration = invoicetronic_sdk.Configuration(
username='YOUR TEST API KEY (starts with ik_test_)',
host='https://api.invoicetronic.com/v1'
)
As you can see, we configure the SDK by passing your test API Key (not the live one) and the API host. Notice how we use the username parameter to set the API Key.
API Key comes in pairs
When you create your account, you obtain a pair of API Keys. One is the test key for the API Sandbox, and the other is the live API's. You can tell the difference because the former starts with ik_test_, while the latter begins with ik_live_. In this tutorial, always use the test key.
Send an invoice
We are ready to make a request. We want to send an invoice to the SDI. Add the following code:
import os
# Send an invoice
file_path = '/some/file/path/filename.xml'
meta_data = {
'internal_id': '123',
'created_with': 'myapp',
'some_other_custom_data': 'value'
}
with invoicetronic_sdk.ApiClient(configuration) as api_client:
send_api = invoicetronic_sdk.SendApi(api_client)
try:
with open(file_path, 'r', encoding='utf-8') as f:
payload = f.read()
send_data = Send(
file_name=os.path.basename(file_path),
payload=payload,
meta_data=meta_data
)
sent_invoice = send_api.send_post(send_data)
print(f"The invoice was sent successfully, it now has the unique Id of {sent_invoice.id}.")
except ApiException as e:
print(f"Error: {e}")
In the terminal, run the application:
You should obtain an output similar to this one:
What we learned
In this example, we learned several things.
-
We must configure the SDK by creating a
Configurationinstance and passing username (API key) and host (API URL). -
We use the
withcontext manager to automatically handle API client closure. We instantiateApiClientpassing the configuration. -
We must instantiate a class representing the endpoint we want to work with. In this case, we leverage
SendApito send invoices. Endpoint classes likeSendApioffer methods for interacting with their target entity. We callsend_post()to send an invoice. -
The
Sendmodel exposes attributes likefile_name,meta_data, andpayload. The last one contains the invoice content, whilemeta_datais optional and binds custom data to the document.
Source Code on GitHub
The source code for this Quickstart is also available on GitHub.