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 SDK sources and full READMEs live in sdk/python and
sdk/typescript.
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.verifyandverify_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 signalsPlanisphereBlocked/PlanisphereNeedsReview(both carry.decision).
Sandbox¶
Get a free ps_test_ key with no card via POST /signup/test-key. Sandbox
receipts are signed with a non-production key (dev_key: true) so they can never
be mistaken for production evidence. Upgrade in place by completing checkout with
the same email.
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).