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.

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-2.0.1.tar.gz (96.5 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-2.0.1-py3-none-any.whl (50.4 kB view details)

Uploaded Python 3

File details

Details for the file django_toconline-2.0.1.tar.gz.

File metadata

  • Download URL: django_toconline-2.0.1.tar.gz
  • Upload date:
  • Size: 96.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for django_toconline-2.0.1.tar.gz
Algorithm Hash digest
SHA256 b5ca007326f7a74fba221229f4a56aafe6aac65c47e9264e185db9b55ea0f475
MD5 f46444b49083b0015f02f8d4fde342d6
BLAKE2b-256 7b20b85adcbb92ca88de9a6df7e0ad32b061ca85eaffdd0a22c3ec23480abf3b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_toconline-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6b2966379c7c1350b4a75377d340f4e589a70157d18ade95df39296450b56cc0
MD5 2211354e6df1159a2d2aec4e7d84b0e2
BLAKE2b-256 f0cd44b4f757d176c1b86a2741cc9e0c7b8ecf79135e675d2128914668f1286d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.1 This release

2 files

2.0.0

2 files

1.1.0

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