Skip to main content

Periplus Python SDK

Typed organization operations and SQL access through the Periplus HTTP API. The 0.11.0 platform interface requires the matching API release. It includes the source-snapshot metadata introduced in 0.10.0 alongside customer operations. Install from PyPI:

python -m pip install --upgrade periplus-python-sdk
from periplus_sdk import Client

with Client("https://api.periplus.dev", api_key="ppl_…") as client:
    result = client.execute(
        "SELECT capture_id, url FROM public_v1.captures LIMIT ?", [10]
    )
    print(result.columns, result.rows)

The default origin is https://api.periplus.dev. Use PERIPLUS_API_URL to override it and PERIPLUS_API_KEY to supply your personal organization API key. A key with organization:sql:exec is required. Database usernames/passwords and anonymous access are not supported. Use HTTPS outside loopback development. Connect directly to the API origin, not the public marketing site.

Version 0.9.0 requires personal API keys instead of database credentials. Create a key in the app's Settings → My API keys. It inherits your current access in that organization; SQL requires your membership to have organization:sql:exec. For local development, install ./clients/periplus-python-sdk from the repository root and connect to http://localhost:8000.

AsyncClient accepts the same options. prepare explains a SELECT; execute returns typed columns/rows for read-only queries. schema() returns visible tables, column types/descriptions and helper documentation. All SQL uses POST /api/v1/sql; schema discovery uses GET /api/v1/schema. ClickHouse enforces permissions. The SDK never retries automatically, including failed queries.

Public HTML joins use parse_id and node_index; document_id identifies exact raw bytes. Public shorthand uses the public_v1 schema.

In 0.10.0, result.source_snapshot is a typed SourceSnapshot containing layout_id (UUID) and publication_epoch (integer), or None when no build-bound public corpus was read. Buffered, asynchronous, streamed and DB-API results share this contract. Compare both fields, not just the epoch. The identity describes the public corpus inputs, not any native staff/external inputs. It does not retain the data or request historical reads. This replaces the old nullable integer field; use this SDK version with the corresponding API release.

For notebook/SQLAlchemy integration:

from periplus_sdk import sql_api
from sqlalchemy import text

engine = sql_api.create_engine(base_url="http://localhost:8000", api_key="ppl_…")
with engine.connect() as connection:
    print(connection.execute(text("SELECT url FROM public_v1.captures LIMIT 5")).all())
engine.dispose()

Marimo discovers accessible tables, views, typed columns and comments through the schema endpoint. Reflection does not execute SQL. One SQLAlchemy Inspector caches its metadata; call inspector.clear_cache() to refresh it. Missing metadata raises an error rather than presenting an apparently complete empty schema.

The DB-API connection advertises the ClickHouse dialect and converts native nullable integer, decimal, date and datetime types. Nested types retain JSON wire values. Writes are not exposed through the query API. There are no client transactions; each statement is independent. Streaming cursors expose incomplete/truncated results explicitly; configure allow_partial only when partial results suit the application.

See the public schema and query boundary.

Organization resources

The same key selects your organization and inherits your live membership access. Client and AsyncClient expose the same namespaces:

Namespace Operations
identity, availability get
discovery create, get, list, iter, arrivals, cancel
retention, monitoring create, preview, activate, get, list, iter, members, update, pause, resume, delete
saved_queries create, get, list, iter, rename, delete
members list, update_role, remove
invitations list, create, cancel
api_keys create, list, iter, revoke
usage get
query_history list, iter, get, summary
audit list, iter
from periplus_sdk import Client

with Client() as client:
    preview = client.retention.preview(
        name="Research sources", days=90,
        sql="SELECT capture_id FROM captures WHERE domain(url) = ?",
        parameters=["example.com"],
    )
    print(preview.id, preview.capture_count, preview.sample)
    # Review the selection before calling:
    # active = client.retention.activate(preview)

SQL previews persist inactive, frozen selections; activation never reruns SQL. Explicit IDs/URLs passed to create activate immediately. Monitoring URLs must already be known in the corpus. Use members and its next_cursor for complete membership: policy detail contains a sample. Updates/deletion accept a fetched Policy or an ID with expected_version; conflicts are never retried.

Paginated lists return Page[T] (items, next_cursor). Pass cursors unchanged or use iter(); membership/invitation lists are bounded snapshots instead. Offset-based lists can shift during concurrent changes. Query history and arrivals use keyset cursors. UTC usage ranges have an exclusive end date, at most 93 days. Query history is best-effort and expires after 30 days; it is not a billing ledger.

ApiError includes HTTP status, code, optional request ID, validation fields and Retry-After seconds. TransportError means the outcome of a write can be unknown. Keep creation IDs to reconcile; never blindly retry. Key creation is one-time: created.secret.get_secret_value() reveals the secret and must only be used for secure storage. Its ordinary representation is masked. Lost secrets cannot be recovered.

For async streaming, use async with await client.stream(sql) as stream followed by async for batch in stream. Streams validate completion and close on early exit, errors, and cancellation. No threads or background polling are introduced.

Release files for periplus-python-sdk 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for periplus-python-sdk 0.11.0
File Size Uploaded
periplus_python_sdk-0.11.0.tar.gz 50.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for periplus-python-sdk 0.11.0
File Interpreter ABI Platform
periplus_python_sdk-0.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 97.4 kB

Release files / periplus_python_sdk-0.11.0.tar.gz

Download URL periplus_python_sdk-0.11.0.tar.gz
Size 50.6 kB
Tags Source
SHA-256 checksum
How to use checksums
00b9142b24e72b81a67e649bc39445441c032299c95c75239987cf67f7d84040
BLAKE2b-256 checksum
How to use checksums
84660799f6afb72a2d5d429e6db096412ade4fde1e33504737f1ffde9aeb5f21
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / periplus_python_sdk-0.11.0-py3-none-any.whl

Download URL periplus_python_sdk-0.11.0-py3-none-any.whl
Size 46.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d89f737e10967eb38d3e79b7552568103fc84a36a4f1fc21640776d92c87d0c
BLAKE2b-256 checksum
How to use checksums
4ab75a729f05e7390d25e837906e8b7220f6d8b722d0e35944df5f54def11d61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.0 This release

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release 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