Skip to main content

Django TOConline

A Django integration and complete OpenAPI client for Portugal's TOConline commercial API.

The package persists OAuth2 tokens and exposes a complete spec-driven OpenAPI client. It returns Pydantic models for documented successful response schemas and raw JSON when the OpenAPI document does not provide a response schema. An opt-in resource view also flattens recognised JSON:API responses for concise application code.

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_OAUTH_REDIRECT_URI = os.environ.get(
    "TOCONLINE_OAUTH_REDIRECT_URI",
    "https://oauth.pstmn.io/v1/callback",
)
TOCONLINE_TIMEOUT = 10

TOCONLINE_BASE_URL is the API host URL without /api. TOCONLINE_OAUTH_BASE_URL is the OAuth service URL; it defaults to <TOCONLINE_BASE_URL>/oauth for backward compatibility.

TOConline test tenants can expose those services on different hosts. In that case configure both explicitly, for example an api10.toconline.pt API host and an app10.toconline.pt OAuth host. Do not point TOCONLINE_BASE_URL at the OAuth host: the client appends /api to that setting.

Complete v2 API client

Version 2.0.1 implements all 120 operations published in TOConline's OpenAPI 1.0.0 document. The v2 client is exposed lazily from the configured Django OAuth transport, so it uses the same secure token persistence, timeout, and host validation.

from toconline.services import toconline
from toconline.api import models

document = toconline.api.sales.create_sales_document(
    body=models.ApiV1CommercialSalesDocumentsPostRequest(
        date="2026-07-22",
        document_type="FT",
        customer_tax_registration_number="999999990",
        lines=[],
    )
)

Body dictionaries are accepted and validated too:

purchase = toconline.api.purchases.finalize_purchase_document(
    id="purchase-document-id",
    body={},
)

Available namespaces are company, catalog, sales, purchases, documents, and auxiliaries. Every endpoint has one English, typed method name, for example toconline.api.company.list_customers(). Each method accepts params= for documented query filters.

See the v2 OpenAPI client guide for the complete developer guide: Django and standalone setup, token storage, extending transports, basic API operations, financial/document workflows, errors, testing, generated models, endpoint registry, and regeneration.

Package maintainers should read the OpenAPI generation and maintenance guide before changing the vendored specification or generated client files.

Without Django

For a CLI, worker, or another Python framework, use the included in-memory OAuth transport instead of writing one:

from toconline.api import DefaultTransport, TocOnlineCredentials

transport = DefaultTransport(
    base_url="https://api10.toconline.pt",
    oauth_base_url="https://app10.toconline.pt/oauth",
    credentials=TocOnlineCredentials(
        client_id="...",
        client_secret="...",
        redirect_uri="https://oauth.pstmn.io/v1/callback",
    ),
)

customers = transport.api.company.list_customers()

DefaultTransport keeps the OAuth token in memory and refreshes it when needed. The Django TocOnline service extends this class and only replaces the token storage with the TocOnlineToken model.

Ergonomic JSON:API resources

transport.api preserves the OpenAPI response exactly. For recognised JSON:API responses, use transport.resources to access fields directly:

services = transport.resources.catalog.list_services()
services[0].accounting_number

customers = transport.resources.company.list_customers()
customers[0].business_name

It can also create known JSON:API envelopes and infer their resource type:

customer = transport.resources.company.create_customer(
    attributes={
        "business_name": "Example, Lda.",
        "tax_registration_number": "999999990",
    }
)

Non-JSON:API results, such as regular objects, PDF bytes, URLs, and empty responses, remain unchanged. See the v2 OpenAPI client guide for request rules, collection endpoints, and the distinction from typed generated models.

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.

Development and tests

The test suite is deterministic and does not contact TOConline or use real credentials.

The OpenAPI transport contract test covers all 120 published operations. An additional opt-in live test exercises every GET operation through the real v2 client without saving OAuth tokens or sending request bodies. It is deliberately off by default and must use a disposable tenant:

cp .env.example .env
# Edit .env with disposable-tenant credentials.
make test-live

make test-live safely loads the key/value pairs from .env only for that test process; it never executes .env as shell code. .env is ignored by Git; .env.example is the versioned template. Do not place production credentials in either local live-test configuration.

Set TOCONLINE_LIVE_CASH_ACCOUNT_ID as well when the tenant has no existing cash account but you need to exercise GET /api/cash_accounts/{id}. Mutating operations remain covered by deterministic contract tests; their live safety policy is enforced by test_live_openapi.py. Do not enable live mutations on a production tenant, or send e-mail / communicate documents to the Tax Authority without a separately approved sandbox workflow.

make requirements-test
make test

To regenerate the checked-in OpenAPI models and endpoint registry after an intentional spec update:

python -m pip install -r requirements-dev.txt
python scripts/generate_openapi_artifacts.py
python scripts/generate_openapi_artifacts.py --check

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 for 2.0.0

  • The package version is now 2.0.0 because the new v2 API has typed OpenAPI response semantics instead of the legacy JSON:API-unwrapping behavior.
  • All 120 operations in the vendored TOConline OpenAPI 1.0.0 document are available under toconline.api and protected by a spec-coverage test.
  • pydantic>=2.12,<3.0 is now a runtime dependency.

Breaking changes in 2.0.0

  • The legacy toconline.resources module and generic TocOnline CRUD, document, and raw-request helpers were removed.
  • Use the complete generated client under toconline.api for every published TOConline operation. Applications that require the legacy surface must keep using a 1.x release.

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.
  • Test settings no longer contain credential-like values, and tests no longer mutate a live TOConline account.

License

MIT. See LICENSE.

Metadata

Release files for django-toconline 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-toconline 2.0.1
File Size Uploaded Provenance Actions
django_toconline-2.0.1.tar.gz 96.5 kB Without provenance Details for django_toconline-2.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-toconline 2.0.1
File Interpreter ABI Platform Actions
django_toconline-2.0.1-py3-none-any.whl Python 3 none any Details for django_toconline-2.0.1-py3-none-any.whl

Total release size: 146.9 kB

Release files / django_toconline-2.0.1.tar.gz

Download URL django_toconline-2.0.1.tar.gz
Size 96.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b5ca007326f7a74fba221229f4a56aafe6aac65c47e9264e185db9b55ea0f475
BLAKE2b-256 checksum
How to use checksums
7b20b85adcbb92ca88de9a6df7e0ad32b061ca85eaffdd0a22c3ec23480abf3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / django_toconline-2.0.1-py3-none-any.whl

Download URL django_toconline-2.0.1-py3-none-any.whl
Size 50.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b2966379c7c1350b4a75377d340f4e589a70157d18ade95df39296450b56cc0
BLAKE2b-256 checksum
How to use checksums
f0cd44b4f757d176c1b86a2741cc9e0c7b8ecf79135e675d2128914668f1286d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Security for django-toconline 2.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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