Metadata-Version: 2.4
Name: unifyport-sdk
Version: 0.1.0
Summary: Type-safe Python SDK for the UnifyPort Device API.
Project-URL: Homepage, https://www.unifyport.ai
Project-URL: Repository, https://github.com/Unify-Port/UnifyPort-SDK-Python
Project-URL: Issues, https://github.com/Unify-Port/UnifyPort-SDK-Python/issues
Author: UnifyPort
License: MIT License
        
        Copyright (c) 2026 UnifyPort
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: device-api,python,sdk,unifyport
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1,>=0.27
Requires-Dist: typing-extensions<5,>=4.13
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: mypy<3,>=1.13; extra == 'dev'
Requires-Dist: pip-audit<3,>=2.7; extra == 'dev'
Requires-Dist: pytest-asyncio<2,>=0.24; extra == 'dev'
Requires-Dist: pytest-cov<8,>=6; extra == 'dev'
Requires-Dist: pytest<10,>=8.3; extra == 'dev'
Requires-Dist: pyyaml<7,>=6; extra == 'dev'
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
Requires-Dist: twine<8,>=6; extra == 'dev'
Description-Content-Type: text/markdown

# UnifyPort Python SDK

[English](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/README.md) |
[简体中文](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/README.zh-CN.md) |
[Website](https://www.unifyport.ai)

Type-safe sync and async Python clients for the public UnifyPort Device API. The SDK is generated from
the approved public OpenAPI contract and currently tracks `@unifyport/sdk-node` `v0.4.0`: 64 operations,
70 component schemas, and the same retry and secret-handling classifications.

The Python package is `unifyport-sdk`; the import package is `unifyport`. This repository starts at SDK
version `0.1.0`. A Git tag or local build alone does not prove that a version reached PyPI.

## Requirements

- Python `>=3.11`
- `httpx` `>=0.27,<1`
- `typing-extensions` `>=4.13,<5` for the Python 3.11-3.13 PEP 728 backport

Install the published package from PyPI:

```bash
python -m pip install unifyport-sdk
```

To work from a source checkout:

```bash
python -m pip install -e ".[dev]"
```

## Quick start

```python
import os

from unifyport import UnifyPortDeviceClient


def required_env(name: str) -> str:
    value = os.environ.get(name)
    if not value:
        raise RuntimeError(f"Missing required environment variable: {name}")
    return value


with UnifyPortDeviceClient(
    base_url=required_env("UNIFYPORT_DEVICE_API_BASE_URL"),
    api_key=required_env("UNIFYPORT_DEVICE_API_KEY"),
) as device:
    workspace = device.get_workspace()
    print(workspace.data)
```

The async client exposes the same generated snake_case operation surface:

```python
import os

from unifyport import AsyncUnifyPortDeviceClient


async def main() -> None:
    async with AsyncUnifyPortDeviceClient(
        base_url=os.environ["UNIFYPORT_DEVICE_API_BASE_URL"],
        api_key=os.environ["UNIFYPORT_DEVICE_API_KEY"],
    ) as device:
        workspace = await device.get_workspace()
        print(workspace.data)
```

Generated operation methods expose path, query, and the allowlisted `x_request_id` header as typed keyword
arguments, plus typed `body=` and `options=` when applicable. Authentication is never an operation argument:

```python
account = device.get_account(account_id="acc_example", x_request_id="req_example")
```

Every call returns `ApiResult[data]` with only filtered metadata: `data`, `status`, and optional
`request_id`. Raw `httpx.Response` objects are intentionally not public.

## Safety boundaries

- `X-Api-Key` comes only from client configuration and is resolved once per logical operation.
- HTTPS is required by default. Explicitly enabled plaintext HTTP remains limited to loopback hosts.
- Redirects are not followed, and credential-bearing requests cannot escape the configured origin or
  base path.
- Automatic retry is restricted to the 19 reviewed operations and the statuses `408`, `429`, `502`,
  `503`, and `504`, plus transport failures. Per-call settings can only tighten the global budget.
- Requests require identity encoding; compressed responses are rejected before raw bodies are streamed
  through the byte limit and parsed as JSON.
- Public errors retain stable status, error code, operation ID, and request ID only; raw response text,
  query strings, credentials, and underlying exception text are not exposed.
- Cursor helpers enforce a finite page limit and reject missing or repeated cursors.
- `provider_profile` and `reply_token` are sensitive outputs. Do not log complete account or message
  responses.

The package does not expose MCP tools, Agent Skills, a generic raw-request escape hatch, provider-specific
orchestration, or an inferred webhook-signature algorithm.

## Contract and generated code

`contracts/device.openapi.yaml` is the only protocol source for generation. The language-neutral policy
file records semantics that cannot be inferred safely from HTTP methods. Do not edit
`src/unifyport/_generated/` or generated API reference pages directly.

```bash
python scripts/generate.py
python scripts/generate.py --check
python scripts/check_node_parity.py --node-repo ../unifyport-sdk-node --node-ref v0.4.0
```

See the [API coverage report](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/docs/api-coverage.md),
[architecture](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/docs/architecture.md),
[security boundaries](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/docs/security.md),
[contract maintenance guide](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/docs/contract-maintenance.md),
[acceptance report](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/docs/acceptance-report.md),
and [release notes](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/docs/release-notes.md).

## Validation

```bash
ruff format --check .
ruff check .
mypy --strict src scripts typing_tests
npx --yes pyright@1.1.411 pyright_tests
pytest
python -m build
twine check dist/*
python scripts/check_public.py dist/*
python scripts/smoke_installed.py
pip-audit
```

## License

The SDK source is available under the
[MIT License](https://github.com/Unify-Port/UnifyPort-SDK-Python/blob/main/LICENSE). The Device API
contract describes the service interface and retains its own license metadata.
