Skip to main content

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.
  • /v1 resources send plain JSON and receipt updates include the receipt ID in the URL.
  • AT communication follows the machine-readable OpenAPI PATCH operation.
  • Email sending now returns parsed response data instead of raising an AttributeError after 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

django_toconline-1.1.0.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_toconline-1.1.0-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

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

Hashes for django_toconline-1.1.0.tar.gz
Algorithm Hash digest
SHA256 0af7da58c717ce88f89d6e2f465402136c43837f18bcd55f7c943ddf0866a239
MD5 ef4bfcad6025c82ae11dc6afd3deced3
BLAKE2b-256 8274208358e186dcb09abe464120fdc7763a6760255f61c05ca32c4774854c3c

See more details on using hashes here.

File details

Details for the file django_toconline-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_toconline-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2879421b3513e924c57445c3be70305b70fa996b359ae120ce8bfcc3a0e9208a
MD5 04724b5df44e3f767f3c5b11ea3eea7d
BLAKE2b-256 506c360b8ca328f64d535999e31ef0373114bd776b08085b9ede56b4ed07a8e0

See more details on using hashes here.

Release history Release notifications | RSS feed

2.0.1

2 files

2.0.0

2 files

This release

1.1.0 This release

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page