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

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_toconline-2.0.0.tar.gz
  • Upload date:
  • Size: 96.0 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.0.tar.gz
Algorithm Hash digest
SHA256 51e55efd5f79c195a8569791c2b658e9a21db3a6c1bf3bf0308169e2013fa9a9
MD5 eee768b8b577d5a67b867b54ac5fd05c
BLAKE2b-256 789d6fdb8f6021eb9f75deeda875b69db79db23bf12002007e07ba30cd4f474b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_toconline-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fba99c7deb0b6d0cf96343c39dba17e2908626e41376c8d64290afc757465b6b
MD5 2b5fb009a3dcccce07661d5633549778
BLAKE2b-256 9550133eacf96765fb3a962336cee25af2d0522fa1207214372cd6432002c812

See more details on using hashes here.

Release history Release notifications | RSS feed

2.0.1

2 files

This release

2.0.0 This release

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