Skip to content

Client SDKs

Official thin clients for the Planisphere compliant-AI API. Both wrap the same HTTP surface — gate an action, get a signed offline-verifiable receipt, route what needs a human — with typed errors and the decision signals. No runtime dependencies (Python: standard library; Node: built-in fetch, Node 18+).

The released clients are available from PyPI and npm. The published 0.1.0 clients cover the gate, review and verification methods below. For completed-event recording, use the HTTP quickstart or a supported connection helper. The record and buffered-client methods in the 0.2.0 source are not yet available from those registries.

Python

pip install planisphere
from planisphere_sdk import Planisphere, PlanisphereNeedsReview, PlanisphereBlocked

ps = Planisphere(api_key="ps_live_...")   # or ps_test_ for a free sandbox key

decision = ps.gate(
    pack="law",
    proposed_action="File this motion with the court.",
    surface="agent",
    source_key="agent:run:42",
    law_context={"matter_band": "litigation", "tool_id": "harvey"},
    idempotency_key="run-42",   # safe to retry — returns the original result, meters once
)

if decision["decision"] == "allow":
    ...  # proceed, and keep decision["evidence_packet"] as your receipt

Prefer exceptions? require_allow raises PlanisphereNeedsReview / PlanisphereBlocked unless the action is allowed.

Node / TypeScript

npm install planisphere-sdk
import { Planisphere, PlanisphereNeedsReview, PlanisphereBlocked } from "planisphere-sdk";

const ps = new Planisphere("ps_live_...");   // or a free ps_test_ sandbox key

const decision = await ps.gate({
  pack: "law",
  proposed_action: "File this motion with the court.",
  surface: "agent",
  source_key: "agent:run:42",
  law_context: { matter_band: "litigation", tool_id: "harvey" },
  idempotencyKey: "run-42",   // safe to retry — returns the original result, meters once
});

if (decision.decision === "allow") {
  // proceed, and keep decision.evidence_packet as your receipt
}

requireAllow throws the decision signals instead of returning them.

What both clients cover

  • gate / require_allow (requireAllow) — gate an action, with an optional idempotency key so retries return the original result and meter once.
  • verify and verify_kit (verifyKit) — check a receipt, or fetch the offline verification recipe.
  • get_record (getRecord) — fetch a stored evidence packet.
  • record_review / review_queue (recordReview / reviewQueue) — the human review loop.
  • Typed errors: PlanisphereError → PlanisphereAuthError (401/403), PlanisphereRateLimited (429, with retry-after), and the decision signals PlanisphereBlocked / PlanisphereNeedsReview (both carry .decision).

Sandbox

Create a free workspace, verify your email, and create a ps_test_ key in the console's Keys tab. No card is required. Sandbox receipts are signed with a non-production key (dev_key: true) so they can never be mistaken for production evidence. Upgrade the same verified workspace from Billing; existing records retain their original signatures.

Webhooks

To receive events (record.sealed, receipt.anchored, verify.failed, meter.threshold) rather than poll, register an event webhook — see webhooks.md.

Payload Retention: Recording Completed Acts

The record verb (POST /v1/record, POST /v1/record/batch) attests completed acts with hash commitments. Planisphere stores hash commitments only — retain your payload to re-prove WHAT was recorded. Archive the payload bytes (or a durable pointer) alongside the returned action_key; every record response repeats this warning in its payload_retention field. For period evidence: GET /tenant/exports/records?from=&to=&cursor= → POST /evidence-packets/seal-bundle/batch (body is {"action_keys": [...]}; POST /v1/record/batch by contrast takes a bare JSON array of record bodies) → GET /v1/records/{action_key}/inclusion-proof (records anchor on the hourly roll-up epoch; a just-sealed record returns 409 with an estimated_next_epoch_at hint until the next epoch).