Metadata-Version: 2.4
Name: platico
Version: 0.1.0
Summary: Official Python SDK for the Platico payment API
Project-URL: Homepage, https://platico.rs
Project-URL: Repository, https://github.com/StonyAiHub/platico-sdks
Project-URL: Changelog, https://github.com/StonyAiHub/platico-sdks/blob/main/packages/python/CHANGELOG.md
Author-email: Platico <support@platico.rs>
License: Copyright (c) 2026 DevPay (TBD legal name)
        
        Proprietary software. Source provided for review and integration purposes
        only. Redistribution, modification, or use outside the scope of integrating
        with the DevPay payment platform requires written permission.
        
        Contact: support@platico.rs
License-File: LICENSE
Keywords: api,payments,platico,sdk,serbia
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: build==1.2.2.post1; extra == 'dev'
Requires-Dist: mypy==1.14.1; extra == 'dev'
Requires-Dist: pip-audit==2.7.3; extra == 'dev'
Requires-Dist: pytest==8.3.4; extra == 'dev'
Requires-Dist: ruff==0.9.2; extra == 'dev'
Requires-Dist: twine==6.0.1; extra == 'dev'
Description-Content-Type: text/markdown

# platico — Python SDK

Official Python SDK for the Platico payment API. Stripe-shaped, **zero runtime
dependencies**, Python 3.9+, fully typed (PEP 561).

> **Status:** v0.1.0 — initial release. API surface stable enough to integrate
> against; minor versions may include breaking changes until v1.0.

## Install

```bash
pip install platico
```

Requires Python 3.9 or newer. Zero runtime dependencies — the SDK uses only the
standard library (`urllib`, `ssl`, `hmac`, `json`).

## Quickstart

```python
import os
from platico import Platico

client = Platico(os.environ["PLATICO_API_KEY"])

intent = client.payment_intents.create({
    "amount": 999,  # minor units — 9.99 RSD
    "currency": "rsd",
    "description": "Order #4581",
})

print(intent["id"], intent["status"])
```

Responses are plain dicts (typed as `TypedDict`s), so unknown new API fields
never break your integration — access them as `intent["id"]`.

## Customers and saved cards

```python
customer = client.customers.create({
    "email": "jane@example.com",
    "name": "Jane Doe",
})

# Walk every customer with auto-pagination — one page in memory at a time.
for c in client.customers.list():
    print(c["id"], c["email"])

# Or collect a bounded slice (limit is required — prevents accidental OOM):
first50 = client.customers.list().auto_paging_to_list(limit=50)
```

The same pagination shape works on every list endpoint: `payment_intents.list`,
`payment_methods.list`, `refunds.list`, `disputes.list`, `events.list`,
`webhook_endpoints.list`. The returned object is also a single page — read
`.data`, `.has_more`, `.url` directly if that's all you need.

## Webhook signature verification

```python
from flask import Flask, request
from platico import construct_event
from platico import (
    WebhookSignatureInvalidError,
    WebhookTimestampStaleError,
    WebhookMalformedHeaderError,
)

app = Flask(__name__)
WEBHOOK_SECRET = os.environ["PLATICO_WEBHOOK_SECRET"]

@app.post("/webhooks/platico")
def webhook():
    try:
        event = construct_event(
            request.get_data(),  # RAW bytes — NOT request.json
            request.headers.get("Platico-Signature", ""),
            WEBHOOK_SECRET,
        )
    except (
        WebhookSignatureInvalidError,
        WebhookTimestampStaleError,
        WebhookMalformedHeaderError,
    ) as err:
        return str(err), 400

    # event is parsed and verified — safe to act on
    print(event["type"], event["data"]["object"])
    return "", 200
```

> **IMPORTANT:** webhooks need the **raw request body bytes**. JSON body parsers
> re-serialize the payload, which changes the bytes and breaks the HMAC. In
> Flask use `request.get_data()`; in Django use `request.body`; in FastAPI use
> `await request.body()`.

## Configuration

```python
Platico(
    api_key,
    api_base="https://api.platico.rs",  # default
    timeout=30.0,                        # seconds, default
    max_network_retries=3,               # retries on 5xx / 429 / network only
    telemetry=False,                     # opt-in only
)
```

Environment variables: `PLATICO_API_BASE` overrides the base URL,
`PLATICO_CLIENT_TELEMETRY=true` opts into telemetry. The API key is passed
explicitly (read it from `PLATICO_API_KEY` yourself — the SDK never reads a key
from the environment implicitly).

## Error handling

```python
from platico import CardError, RateLimitError, ApiError

try:
    client.payment_intents.create({"amount": 999, "currency": "rsd", "confirm": True})
except CardError as err:
    print("Declined:", err.code, err.decline_code)
except RateLimitError as err:
    print("Slow down, retry after:", err.retry_after)
except ApiError as err:
    print(err.status_code, err.code, err.request_id)
```

Error objects never carry your API key, the request/response body, headers, or a
stack trace — `err.to_dict()`, `repr(err)`, and logging are all leak-safe.

## Security

- The SDK refuses non-HTTPS `api_base` URLs unless the host is
  `localhost` / `127.0.0.1` / `::1`.
- **TLS is always verified** (certificate chain + hostname) via the system trust
  store. There is no option to disable it.
- API keys are never written to logs or attached to error objects (not even via
  a traceback or `pickle`).
- Webhook signature verification uses `hmac.compare_digest` (constant time) with
  replay protection — rejects both stale and future-dated timestamps.
- Auto-generated `Idempotency-Key` on every mutating request; the same key is
  sent on every retry.
- Retries attempt only on `5xx`, `429`, and network errors. Never on other
  `4xx`.

Report security issues to security@platico.rs. See
[SECURITY.md](https://github.com/StonyAiHub/platico-sdks/blob/main/SECURITY.md).

## Supply-chain trust

- **Zero runtime dependencies** — imports only the Python standard library. No
  transitive surface to audit.
- **No install-time code** — declarative `hatchling` build backend, no `setup.py`
  with executable logic, no build/lifecycle hooks. Installing `platico` cannot
  run arbitrary code.
- **PyPI Trusted Publishing (OIDC)** + **PEP 740 attestations** — from the first
  CI-published release, every artifact is linked to the exact GitHub Actions run
  and commit SHA that built it. No long-lived publish token exists.
- **Artifact file allowlist** — the wheel/sdist contain only the source package,
  README, LICENSE, and CHANGELOG. Asserted in CI before every publish.
- **Pinned GitHub Actions** — every workflow `uses:` pins a full commit SHA.

Detailed posture in
[SECURITY.md](https://github.com/StonyAiHub/platico-sdks/blob/main/SECURITY.md).

## License

Proprietary. See [LICENSE](./LICENSE).
