Plainrouter Python SDK and CLI
Generated from Plainrouter's signed OpenAPI contract. The package is in 0.x and its API may change between minor releases. No support guarantees are made yet.
Official project: plainrouter.com · documentation · source
Report Python SDK issues in the Plainrouter SDK issue tracker.
Install
python -m pip install plainrouter
Python 3.11 or newer is required.
For command-line use, install the same package in an isolated environment:
pipx install plainrouter
plainrouter --help
You can also run the CLI from an active Python environment with
python -m plainrouter. The PyPI CLI provides the same command tree, config
path, environment variables, JSON output, and safety prompts as
@plainrouter/cli.
Use
from plainrouter import create_client, list_events
client = create_client("your-signal-tracker-secret")
response = list_events.sync(client=client)
Async operations are available through each operation module:
from plainrouter import create_client, get_event
client = create_client("your-signal-tracker-secret")
response = await get_event.asyncio(event="event-id", client=client)
The default API base is https://plainrouter.com/api/v1 and the default request timeout is 30 seconds. Pass base_url or an httpx.Timeout to create_client to override either setting. Credentials are supplied by the caller and are never embedded in the SDK.
Copy a failed plan to a fresh draft using a plan-writer bearer token:
import os
from plainrouter import create_client, launch_plans_copy
client = create_client(os.environ["PLAINROUTER_TOKEN"])
response = launch_plans_copy.sync_detailed(1, "failed-plan-id", client=client)
The same operation provides asyncio and asyncio_detailed entry points. The
public plainrouter.launch_plans_copy.PlanCopyResponse type alias describes the
parsed result union, including ProposalUnavailable and WorkspaceLockTimeout.
The detailed entry points return Response[PlanCopyResponse]; sync and
asyncio return PlanCopyResponse | None.
Retryable proposal errors
Pass the detailed response or raw HTTPX response to the helper, including for
async calls and endpoints with no documented 503. It recognizes only 503 error
envelopes with a string message and either workspace_lock_timeout or
proposal_not_recorded; other bodies return False.
import json
from plainrouter import is_retryable_proposal_error
retryable = is_retryable_proposal_error(response.status_code, response)
error_code = json.loads(response.content)["error"]["code"] if retryable else None
retry_after = response.headers.get("Retry-After") if retryable else None
This example also distinguishes lock timeout (error_code == "workspace_lock_timeout") without relying on response.parsed. If generated
parsing raises before returning a detailed response, capture the raw response
with an HTTPX response hook and call response.read() there; in an async hook,
await response.aread(). Run the same example on that captured response. Use
the public copy facade rather than calling generated copy directly.
No automatic retry is added. Honor Retry-After when present (delta seconds or
an HTTP date) when scheduling a retry.
Licensed under Apache-2.0.
Use create_client() or the hand-written plainrouter.AuthenticatedClient / plainrouter.Client for JSON negotiation and redirect protection. Headers default to Accept: application/json; override with client.with_headers({"Accept": "..."}) or constructor headers. A 3xx raises httpx.HTTPStatusError before parsing or following, even with follow_redirects=True; inspect error.response.status_code and error.response.headers["Location"]. The separate generated namespace provides raw clients without this policy.
Header names merge case-insensitively, including repeated with_headers calls
and clients derived after first use. In-place updates to a live client also merge
names case-insensitively: if a dict names Accept or Authorization in multiple
letter cases, the last spelling in caller order wins and sends exactly one line.
On a token client, the client with_headers returns always sends the SDK's own
token as Authorization; the live client and an injected client send the caller's
last spelling.
Injected HTTPX clients receive JSON Accept
when it is absent or exactly */* (HTTPX's automatic default is indistinguishable
from an explicit wildcard); any other configured value is retained. To request
an explicit wildcard after injection, use client.with_headers({"Accept": "*/*"}).
set_httpx_client and set_async_httpx_client set Accept on the HTTPX client
object you pass in, so other code sharing that object sees the change.
Metadata
Release files for plainrouter 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| plainrouter-0.10.0.tar.gz | 227.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| plainrouter-0.10.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 950.0 kB
Release files / plainrouter-0.10.0.tar.gz
| Download URL | plainrouter-0.10.0.tar.gz |
|---|---|
| Size | 227.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0c1071826da24aef3b13809bf11a9294853c2870db7e341269dff682b8937790
|
|
BLAKE2b-256 checksum How to use checksums |
d6b8b6643aeb0a894eed2a3ebca2993dbcd8d8fb99f7089b4cfa1dd0dbc08db5
|
| 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 Oct 15, 2026.
Transparency logRelease files / plainrouter-0.10.0-py3-none-any.whl
| Download URL | plainrouter-0.10.0-py3-none-any.whl |
|---|---|
| Size | 722.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9553fc9c05cfa49e62074a948b2d2919b54a499cdfea12640d1ffce2e2f56313
|
|
BLAKE2b-256 checksum How to use checksums |
dea74a8f9f4af4e933ab1e175384761c3b961e8560dbb30ad0a8c7d427dbae52
|
| 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 Oct 15, 2026.
Transparency log