Metadata-Version: 2.5
Name: opendpp-sdk
Version: 1.14.0
Summary: Official Python SDK for the OpenDPP Digital Product Passport API — a fully-typed client (pydantic v2) generated from the public OpenAPI contract and version-locked to it.
Project-URL: Homepage, https://github.com/OpenDPP/opendpp-sdk
Project-URL: Repository, https://github.com/OpenDPP/opendpp-sdk
Project-URL: Issues, https://github.com/OpenDPP/opendpp-sdk/issues
Project-URL: Changelog, https://github.com/OpenDPP/opendpp-sdk/blob/main/CHANGELOG.md
Author-email: Giovanni Savastano <giovanni.savastano@opendpp-node.eu>
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: api-client,digital-product-passport,dpp,espr,openapi,opendpp,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: pydantic>=2
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: typing-extensions>=4.7.1
Requires-Dist: urllib3<3.0.0,>=1.25.3
Description-Content-Type: text/markdown

# opendpp-sdk

Official **Python SDK** for the [OpenDPP](https://opendpp-node.eu) Digital Product Passport API — a
fully-typed client (pydantic v2 + urllib3, synchronous) mechanically generated from the public
OpenAPI contract ([`openapi.json`](openapi.json)) and **version-locked** to it: this package's
MAJOR.MINOR *is* the contract version it targets.

The only hand-written code is the thin [`opendpp_sdk.ergonomics`](opendpp_sdk/ergonomics.py) module.
Everything else under `opendpp_sdk/` is generator-owned, regenerated by
[`scripts/regenerate.sh`](scripts/regenerate.sh) and drift-checked in CI.

## Install

```bash
pip install opendpp-sdk
```

Python ≥ 3.9. Runtime dependencies: `pydantic>=2`, `urllib3`, `python-dateutil`, `typing-extensions`.

## Quick start

```python
import os

from opendpp_sdk.api.passports_api import PassportsApi
from opendpp_sdk.api.service_api import ServiceApi
from opendpp_sdk.ergonomics import create_opendpp_client

client = create_opendpp_client(api_key=os.environ["OPENDPP_API_KEY"])

health = ServiceApi(client).get_health()          # public — works without a key too
passports = PassportsApi(client)
created = passports.create_passport({"productId": "09501101530003", "metadata": {"category": "batteries", ...}})
```

`create_opendpp_client()` defaults to the public hosted node (`https://opendpp-node.eu`); pass
`base_url=` for a workspace host. The API key is sent as `Authorization: Bearer …` on operations
that declare a security requirement — public operations (the resolvers, the validators, the audit
verifier) work without one.

### Content-negotiated public resolvers

The 200 of `GET /passport/{id}`, `/01/{gtin14}`, `/8003/{grai}` and `/unit/{id}` is negotiated via
the `Accept` header (JSON-LD default / AAS / VC-JWT / VC-LD / SD-JWT-VC / HTML). The generated
operations are typed against the default JSON-LD document; the `resolve_*_as` helpers are the
supported way to request an alternate representation — they set the `Accept` header AND the
matching body parsing, and type the result per media type:

```python
from opendpp_sdk.ergonomics import resolve_public_passport_as

doc = resolve_public_passport_as(client, passport_id, "application/ld+json")   # PublicPassportJsonLd
aas = resolve_public_passport_as(client, passport_id, "application/aas+json")  # AasEnvironment
jws = resolve_public_passport_as(client, passport_id, "application/vc+jwt")    # compact JWS str
```

### Tolerant by design

Response models never reject unknown fields — a future MINOR server release may add response
fields, and deployed clients must keep working. Unknown keys are captured losslessly in each
model's `additional_properties`.

## Versioning

This package's version is locked to the API contract at **major.minor** (enforced by
[`scripts/check_version_lock.py`](scripts/check_version_lock.py)); the PATCH digit is the SDK's own
fix lane, so a client-only fix can ship against an unchanged contract. Pin the MAJOR — a breaking
contract change ships as a new `/api/vN` path major.

## Regenerating

```bash
./scripts/regenerate.sh   # normalize the vendored spec, wipe, regenerate (needs node + a JRE)
```

The generation input is the vendored contract rewritten by the shared normalizer
([`../scripts/normalize-spec.mjs`](../scripts/normalize-spec.mjs) — authored and unit-tested in the
OpenDPP node repository, synced here); the vendored `openapi.json` itself stays the pristine
published contract. Generated sources are committed; CI regenerates and fails on any diff.

## License

Apache-2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE). "OpenDPP" is a trademark of Opendpp UAB;
the license grants no rights to the marks (see [TRADEMARK.md](../TRADEMARK.md)).
