Official Python SDK for the Platico payment API
Project description
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
pip install platico
Requires Python 3.9 or newer. Zero runtime dependencies — the SDK uses only the
standard library (urllib, ssl, hmac, json).
Quickstart
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 TypedDicts), so unknown new API fields
never break your integration — access them as intent["id"].
Customers and saved cards
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
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 userequest.body; in FastAPI useawait request.body().
Configuration
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
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_baseURLs unless the host islocalhost/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-Keyon every mutating request; the same key is sent on every retry. - Retries attempt only on
5xx,429, and network errors. Never on other4xx.
Report security issues to security@platico.rs. See SECURITY.md.
Supply-chain trust
- Zero runtime dependencies — imports only the Python standard library. No transitive surface to audit.
- No install-time code — declarative
hatchlingbuild backend, nosetup.pywith executable logic, no build/lifecycle hooks. Installingplaticocannot 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.
License
Proprietary. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file platico-0.1.0.tar.gz.
File metadata
- Download URL: platico-0.1.0.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa7da1f8686411444e4f0d5499fdc56febac0406a4c5e34a06c302604c1c09d0
|
|
| MD5 |
38ed540f9ec7ff40244036f5168a0ad9
|
|
| BLAKE2b-256 |
37c0e64e1b67427a53b34a191ff5f678adfba96c365b6f4d679fed39b4c5d557
|
Provenance
The following attestation bundles were made for platico-0.1.0.tar.gz:
Publisher:
publish-python.yml on StonyAiHub/platico-sdks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
platico-0.1.0.tar.gz -
Subject digest:
aa7da1f8686411444e4f0d5499fdc56febac0406a4c5e34a06c302604c1c09d0 - Sigstore transparency entry: 1796976529
- Sigstore integration time:
-
Permalink:
StonyAiHub/platico-sdks@e3d55efdbafa12f7ee93b975181719f5e529b46b -
Branch / Tag:
refs/tags/python-v0.1.0 - Owner: https://github.com/StonyAiHub
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@e3d55efdbafa12f7ee93b975181719f5e529b46b -
Trigger Event:
push
-
Statement type:
File details
Details for the file platico-0.1.0-py3-none-any.whl.
File metadata
- Download URL: platico-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3904c4e9952c3dea51b0e0563dc7ba44846e2bc18dc042dd60881f1ff1103f5
|
|
| MD5 |
2c82e9525655fb5e6e3c187d8f7c201d
|
|
| BLAKE2b-256 |
f54dd12c91d26fbe94769912ef013d8399675b69749c67cbde5df8a004f47d88
|
Provenance
The following attestation bundles were made for platico-0.1.0-py3-none-any.whl:
Publisher:
publish-python.yml on StonyAiHub/platico-sdks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
platico-0.1.0-py3-none-any.whl -
Subject digest:
f3904c4e9952c3dea51b0e0563dc7ba44846e2bc18dc042dd60881f1ff1103f5 - Sigstore transparency entry: 1796976598
- Sigstore integration time:
-
Permalink:
StonyAiHub/platico-sdks@e3d55efdbafa12f7ee93b975181719f5e529b46b -
Branch / Tag:
refs/tags/python-v0.1.0 - Owner: https://github.com/StonyAiHub
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@e3d55efdbafa12f7ee93b975181719f5e529b46b -
Trigger Event:
push
-
Statement type: