Django TOConline
A small Django integration for Portugal's TOConline commercial API.
The package deliberately stays close to the HTTP API: it persists OAuth2
tokens, provides generic resource helpers, and implements the few document
operations whose routes do not follow normal CRUD conventions. API responses
are returned as dictionaries/lists, with the outer JSON:API data member
removed when present.
Official sources:
Compatibility
| Django | Python |
|---|---|
| 5.2 | 3.10–3.14 |
| 6.0 | 3.12–3.14 |
Django 6.0 itself requires Python 3.12 or newer. The package retains Django 5.2 support so applications still on Python 3.10 or 3.11 have a supported upgrade path.
Installation
python -m pip install django-toconline
Add the application to INSTALLED_APPS and run migrations:
INSTALLED_APPS = [
# ...
"toconline",
]
python manage.py migrate
Configuration
Keep all credentials in environment-backed settings. TOConline supplies the API URL and OAuth URL with the integration credentials for each company.
import os
TOCONLINE_BASE_URL = os.environ["TOCONLINE_BASE_URL"]
TOCONLINE_OAUTH_BASE_URL = os.environ.get(
"TOCONLINE_OAUTH_BASE_URL",
f"{TOCONLINE_BASE_URL}/oauth",
)
TOCONLINE_OAUTH_CLIENT_ID = os.environ["TOCONLINE_OAUTH_CLIENT_ID"]
TOCONLINE_OAUTH_CLIENT_SECRET = os.environ[
"TOCONLINE_OAUTH_CLIENT_SECRET"
]
TOCONLINE_ALLOWED_DOWNLOAD_HOSTS = ["toconline.pt"]
TOCONLINE_OAUTH_REDIRECT_URI = os.environ.get(
"TOCONLINE_OAUTH_REDIRECT_URI",
"https://oauth.pstmn.io/v1/callback",
)
TOCONLINE_TIMEOUT = 10
TOCONLINE_BASE_URL is the host URL without /api.
TOCONLINE_OAUTH_BASE_URL is the OAuth service URL ending in /oauth; it
defaults to <TOCONLINE_BASE_URL>/oauth for backward compatibility.
TOCONLINE_ALLOWED_DOWNLOAD_HOSTS is optional. Official *.toconline.pt
API hosts allow that domain's subdomains by default; custom/white-label API
hosts should explicitly list every trusted PDF download host.
Resource operations
Authentication is automatic. The first request obtains and stores a token in
TocOnlineToken; subsequent requests refresh it before expiry.
Token values are deliberately hidden from Django admin, but the application
database and its backups must still be treated as sensitive.
from toconline.resources import TocOnlineResource
from toconline.services import toconline
customers = toconline.list(
TocOnlineResource.CUSTOMERS,
limit=10,
)
customer = toconline.first(
TocOnlineResource.CUSTOMERS,
email="customer@example.com",
)
created = toconline.create(
TocOnlineResource.CUSTOMERS,
business_name="Example, Lda.",
contact_name="Example",
tax_registration_number="999999990",
)
toconline.update(
TocOnlineResource.CUSTOMERS,
created["id"],
contact_name="Updated name",
)
toconline.delete(TocOnlineResource.CUSTOMERS, created["id"])
Keyword arguments to list() become JSON:API filters. Raw query parameters
are also supported for TOConline's expression filters and pagination:
documents = toconline.list(
TocOnlineResource.COMMERCIAL_SALES_DOCUMENTS,
params={
"filter": "documents.pending_total>0",
"page[size]": 25,
},
)
The current /v1 sales and purchase creation endpoints use plain JSON rather
than a JSON:API envelope. create() handles that distinction automatically.
Current receipt updates also use the ID-scoped /v1 route.
receipt = toconline.create(
TocOnlineResource.COMMERCIAL_SALES_RECEIPTS,
date="2026-07-22",
payment_mechanism="TR",
lines=[
{
"receivable_type": "Document",
"receivable_id": "123",
"received_value": 100,
}
],
)
toconline.update(
TocOnlineResource.COMMERCIAL_SALES_RECEIPTS,
str(receipt["id"]),
observations="Updated before finalization",
)
The generic helpers are path-driven. They do not imply that every TOConline resource supports every CRUD operation; use only the methods listed for that resource in the official documentation.
Document operations
Download a PDF
from toconline.resources import TocOnlineDocumentKind
pdf = toconline.download_document(
"document-id",
kind=TocOnlineDocumentKind.DOCUMENT,
n_copies=2,
)
Available print kinds are Document, Receipt, and the currently documented
PurchasesDocument. The historical enum member name PURCHASE_DOCUMENT
remains available but now sends the corrected plural API value.
Void a supported document
toconline.void_document(
TocOnlineResource.COMMERCIAL_SALES_RECEIPTS,
"receipt-id",
)
The old cancel_document() name remains as an alias.
Send a document by email
result = toconline.send_document_via_email(
from_email="billing@example.com",
from_name="Billing",
subject="Your invoice",
to_email="customer@example.com",
pk="document-id",
kind=TocOnlineDocumentKind.DOCUMENT,
)
Communicate a document to the Tax Authority
from toconline.resources import TocOnlineTaxAuthorityDocumentType
result = toconline.communicate_document_to_tax_authority(
"document-id",
document_type=TocOnlineTaxAuthorityDocumentType.SALES_DOCUMENT,
entity_username="tax-portal-user",
entity_password="base64-encoded-tax-portal-password",
)
The misspelled historical method
send_document_to_finantial_authority() remains as an alias. Never log the
Tax Authority username or password.
Calling newly added endpoints
Use request() when TOConline publishes a route before this package adds a
convenience constant. Paths are relative to /api; absolute URLs and ..
path traversal are rejected so bearer credentials cannot be sent to another
host.
result = toconline.request(
"GET",
"new-resource",
params={"page[size]": 10},
)
Development and tests
The test suite is deterministic and does not contact TOConline or use real credentials.
make requirements-test
make test
To expose deprecation warnings during framework upgrades:
.venv/bin/python -Wa manage.py test tests
CI covers the lower supported Python/Django pair, Django 6 on its minimum Python version, and the newest supported Python/Django pair.
Upgrade notes from 1.0.x
- The supported Django range is now
>=5.2,<7.0, which permits Django 6. - OAuth and API hosts may be configured separately.
/v1resources send plain JSON and receipt updates include the receipt ID in the URL.- AT communication follows the machine-readable OpenAPI
PATCHoperation. - Email sending now returns parsed response data instead of raising an
AttributeErrorafter a successful request. - The purchase print type is
PurchasesDocument, matching the current docs. - PDF downloads reject hosts outside the TOConline domain by default; custom
API installations must set
TOCONLINE_ALLOWED_DOWNLOAD_HOSTS. - Test settings no longer contain credential-like values, and tests no longer mutate a live TOConline account.
License
MIT. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_toconline-1.1.0.tar.gz.
File metadata
- Download URL: django_toconline-1.1.0.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0af7da58c717ce88f89d6e2f465402136c43837f18bcd55f7c943ddf0866a239
|
|
| MD5 |
ef4bfcad6025c82ae11dc6afd3deced3
|
|
| BLAKE2b-256 |
8274208358e186dcb09abe464120fdc7763a6760255f61c05ca32c4774854c3c
|
File details
Details for the file django_toconline-1.1.0-py3-none-any.whl.
File metadata
- Download URL: django_toconline-1.1.0-py3-none-any.whl
- Upload date:
- Size: 13.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2879421b3513e924c57445c3be70305b70fa996b359ae120ce8bfcc3a0e9208a
|
|
| MD5 |
04724b5df44e3f767f3c5b11ea3eea7d
|
|
| BLAKE2b-256 |
506c360b8ca328f64d535999e31ef0373114bd776b08085b9ede56b4ed07a8e0
|