Python SDK
Use the peoplescourt Python client to prepare filings, manage account authorization, submit evidence, and follow case events. It supports synchronous and asynchronous applications on Python 3.10 or later. For a complete platform flow, see Integrate a marketplace dispute.
Install the prepared beta
The MIT-licensed Python SDK beta 0.1.0b1 is prepared for publication and is not yet on PyPI. Contact contact@peoplescourt.ai to request the prepared distribution or source access. With the release wheel, install it in your application’s virtual environment:
python -m pip install ./peoplescourt-0.1.0b1-py3-none-any.whl
# Or, from a source checkout:
python -m pip install -e ./sdk/python
# Include Ed25519 callback verification when your integration needs it:
python -m pip install -e './sdk/python[webhooks]'After publication, the pinned PyPI installation command is python -m pip install 'peoplescourt==0.1.0b1'. The source package version is 0.1.0b1. Record the source revision alongside that version when deploying your integration. MIT applies to the Python client distribution; it does not license undistributed server code or grant hosted API access. Platform access remains subject to approval and separately issued live credentials. You can use the public HTTP quickstart without the SDK or a source checkout. JavaScript and TypeScript integrations can use the fetch examples in the endpoint reference.
Connect to the API
Obtain credentials through Get access. An account OAuth token acts only for its approving account and scopes. A registered agent’s client-credentials token acts for that agent account. Platforms acting for many users need approved, role-bound partner credentials and each principal’s authority.
Set PEOPLESCOURT_BASE_URL to your deployment’s origin, without /api, and keep PEOPLESCOURT_TOKEN in your backend secret store. Use a non-production deployment with its matching credentials for evaluation. The client’s default origin is https://peoplescourt.ai; confirming a filing there can open a real proceeding.
import os
from peoplescourt import Client
with Client(
os.environ["PEOPLESCOURT_TOKEN"],
base_url=os.environ["PEOPLESCOURT_BASE_URL"],
timeout=30.0,
) as court:
rules = court.current_rules()
case = court.get_case(os.environ["PEOPLESCOURT_CASE_ID"])
print(case["stage"], case["revision"])Most results unwrap the API’s data object and retain its camelCase field names. Filing, invitation and pagination methods return typed objects instead. Client closes its connections when the with block ends.
Prepare and confirm a filing
The account OAuth example below uses the request body from Get started, saved as filing.json after the claimant reviews its contents. The required scopes include filings:write, consents:write and cases:read. Partner filings use a different request contract with registered authority and confirmation proofs; follow the marketplace walkthrough.
import json
import os
from peoplescourt import AcceptanceRequired, Client, Confirmation, FilingFeeRequired
with Client(
os.environ["PEOPLESCOURT_TOKEN"],
base_url=os.environ["PEOPLESCOURT_BASE_URL"],
) as court:
with open("filing.json", encoding="utf-8") as source:
filing = json.load(source)
draft = court.prepare_filing(filing, idempotency_key="order-1042-prepare")
# Deliver draft.hosted_acceptance_url privately to the claimant.
# Continue only after the claimant reviews and accepts on People’s Court.
input("Continue after the claimant has accepted the exact review packet: ")
result = court.confirm_filing(draft.filing_id, idempotency_key="order-1042-confirm")
if isinstance(result, Confirmation) and result.case_id:
case = court.get_case(result.case_id)
elif isinstance(result, AcceptanceRequired):
# Deliver the returned link privately when present; do not log it.
acceptance_url = result.hosted_acceptance_url
elif isinstance(result, FilingFeeRequired):
# Hand off the returned payment link or details["filingPath"] to the owner.
payment_url = result.filing_payment_urlPreparing a draft does not open a case. The principal must accept the exact claim, Rules, resolved procedure, disclosures and fees. Choose AI-only or AI-assisted human in that packet; the Court resolves the AI-only procedure before acceptance. A human appeal remains available unless both parties separately accept the exact waiver. The SDK cannot perform personal hosted acceptance or infer consent from a credential.
confirm_filing returns Confirmation, AcceptanceRequired or FilingFeeRequired. The two prerequisite results are values rather than raised exceptions; neither opens a case. Check Confirmation.case_id before continuing. Show-once acceptance and invitation links are omitted from ordinary replays; preserve them through the intended recipient’s authenticated channel.
Submit a party’s evidence
Read get_case before writing and follow its availableActions, requirements and effective deadlines. After the party has affirmed truthfulness, use submit_brief with that party’s credential and actual declaration:
import os
from peoplescourt import Client
with Client(
os.environ["PEOPLESCOURT_TOKEN"],
base_url=os.environ["PEOPLESCOURT_BASE_URL"],
) as court:
with open("receipt.txt", "rb") as receipt:
attachment = receipt.read()
submission = court.submit_brief(
os.environ["PEOPLESCOURT_CASE_ID"],
party="claimant",
brief="Order #1042 was paid for and never arrived.",
attest=True,
declaration={
"declarantName": "Maya Chen",
"declarantCapacity": "Individual party",
"executionLocation": "Brussels, Belgium",
},
files=[("receipt.txt", attachment, "text/plain")],
idempotency_key="order-1042-claimant-evidence",
)Replace the example declaration with the actual declarant and location. Files are (filename, bytes, media_type) tuples held in memory. The client sends multipart data and x-pc-party, including when there are no attachments. It does not grant access to an opponent’s sealed filing.
Follow cases and events
| Method | Result and use |
|---|---|
get_case(case_id) | Current authorized case view, including stage, revision, availableActions and waitingOn |
list_cases() / iter_cases() | Account-only case listing; CasePage.cases and .next_url, or iteration across the Link-header pages |
events(case_id, after=cursor) | EventPage.events, .next_cursor and .has_more; persist the cursor with successfully processed work |
iter_events(case_id, after=cursor) | Drains currently available pages and stops; schedule subsequent reads yourself |
create_invitation(case_id, idempotency_key=key) | Invitation.hosted_link; creating a new invitation rotates the old one |
get_answer_requirements(case_id) | The invited respondent’s current Complaint, claim IDs and Answer requirements |
prepare_answer(case_id, body) / confirm_answer(answer_id) | Prepare an account Answer for hosted acceptance, then file the already accepted packet |
Case-list and case-event cursors are different and cannot be interchanged. The marketplace walkthrough shows durable polling checkpoints and signed callback handling.
Use account OAuth
Register the client and exact redirect URI at Account authorizations. authorization_url(client_id, redirect_uri, scopes) builds an S256 PKCE request and retains its verifier and state. Keep that authorization object server-side through the callback, then call login.callback_code(callback_url) to validate the destination, state and issuer. Pass the returned code, login.code_verifier and login.redirect_uri to court.exchange_code on a client constructed with oauth=OAuth(client_id, ...).
Restore saved grants with OAuth(client_id, tokens=saved_tokens, on_token=persist_tokens). The synchronous on_token callback receives a TokenSet on every rotation: persist it durably before returning. One process must own each rotating grant; the client’s lock does not coordinate multiple workers. An uncertain refresh is not automatically retried, and consent_required requires renewed authorization. Registered autonomous agents use OAuth(client_id, client_secret=secret) with client_credentials(scopes) and obtain another token when it expires. For another deployment, pass its configured API audience as resource to both the authorization helper and OAuth, and its origin as base_url to the helper and client. See Authentication for the exact grants and scopes.
Use async Python
import asyncio
import os
from peoplescourt import AsyncClient
async def main():
async with AsyncClient(
os.environ["PEOPLESCOURT_TOKEN"],
base_url=os.environ["PEOPLESCOURT_BASE_URL"],
) as court:
case = await court.get_case(os.environ["PEOPLESCOURT_CASE_ID"])
print(case["stage"])
async for event in court.iter_events(os.environ["PEOPLESCOURT_CASE_ID"]):
print(event["id"], event["type"])
asyncio.run(main())AsyncClient has the same operation names, with awaited requests and async iterators.
Handle errors and retries
APIError exposes status, code, request_id, details, retry_after and idempotency_key. Its subclasses include AuthenticationError, InsufficientScopeError, ConflictError, ValidationError and RateLimitError. Network failures use TransportError; malformed responses use ProtocolError. All derive from PeoplesCourtError.
Supply and durably store an explicit idempotency_key for every business mutation and reuse it only with the identical request. The SDK generates a key when omitted, but that does not recover the same operation after your process restarts. There are no automatic mutation or rate-limit retries. Honor RateLimitError.retry_after, refresh case state after a conflict, and preserve the sent key on uncertain outcomes. OAuth code exchange and refresh must not be replayed as ordinary idempotent writes.
Verify signed callbacks
With the webhooks extra installed, verify_webhook checks Ed25519 signatures, the exact body digest, path and query, timestamp, schema version and signing-key validity:
from peoplescourt import verify_webhook
def verified_event_id(raw_body, headers, actual_path_and_query, trusted_key_set):
return verify_webhook(
raw_body,
headers,
target_path=actual_path_and_query,
keys=trusted_key_set["keys"],
)Load verification keys from the configured trusted Court origin’s /.well-known/peoples-court-webhook-keys.json, applying your signing-key trust and rotation policy. Use the untouched request bytes and receiver path/query. Durably deduplicate and enqueue the verified event ID before acknowledging, then fetch current case state. Invalid verification raises WebhookVerificationError. Registration requires a partner platform_orchestrator credential with callbacks:manage; account OAuth cannot register callbacks.
Operations that use the HTTP API
This Python beta has no dedicated record-summary confirmation, record-export, Award-download or Award-signature verification methods. Use the documented HTTP operations for those steps and apply a separate Award verification policy. verify_webhook verifies callbacks, not Awards. The private TypeScript client is not a distributed public SDK. The endpoint reference provides public curl, TypeScript/fetch and Python HTTP examples for the remaining operations.