Phosra ships a first-party TypeScript SDK. Every other language
talks to the same plain-JSON REST API — and because that API is described by a
published OpenAPI 3.1 document, you can generate a fully-typed client in your
language in about a minute. This page runs the real generators end-to-end against the
live sandbox and pastes the
actual output, including one generated-client call that returns 201.
Verified copy-paste. Every command on this page was run on 2026-07-06 against
the hosted spec at https://phosra-api-sandbox-production.up.railway.app/openapi.yaml
with openapi-generator-cli7.23.0, openapi-typescript7.13.0, and
openapi-fetch0.13. The TypeScript, Python, and Go clients each made the same
live POST /setup/quick call and printed the same three lines:
Emma's Family / preteen / 20.
Which spec do I generate from?
Phosra publishes three OpenAPI documents. Pick the one that matches what you are
building — generating from the wrong spec gives you endpoints you can't call.
Building a parental-controls app — families, children, policies, rules, enforcement, quick-setup. This is the one almost everyone wants. Also mirrored at docs.phosra.com/openapi.yaml.
Managing your provider account — developer orgs, API keys, federation, advisors. Org/key/usage management authenticates with your WorkOS session bearer, not a phosra_ key (see Create your account & get keys).
Building an OCSS gatekeeper / resolver — signed profile reads, binding, §8.3.8 confirmations. See the signing caveat below before you generate.
The sandbox host serves the product API spec (/openapi.yaml) so generated
clients can point straight at a live server. The two split specs
(openapi.control-plane.yaml, openapi.data-plane.yaml) are served from the docs
site. All three are the same documents that drive the API Reference.
Prerequisites
For TypeScript
Node.js 18+. Uses openapi-typescript (types) + openapi-fetch (runtime). No
Java, no code to vendor — types only.
For Python / Go / Java / others
Java 11+ on your PATH (the openapi-generator engine is a JAR) plus Node
to run npx @openapitools/openapi-generator-cli. Check with java -version.
TypeScript — openapi-typescript + openapi-fetch
The idiomatic TS path is types-only generation paired with a tiny typed fetch
wrapper — no generated client code to vendor, and full autocomplete on every path,
body, and response.
Prefer a batteries-included, hand-maintained client? Skip generation and use the
first-party @phosra/sdk (PhosraClient) — it wraps the same
API with retries and token management.
This writes a full installable package: one *_api.py module per tag
(quick_setup_api.py, families_api.py, policies_api.py, …) plus Pydantic models
for every schema (QuickSetupRequest, QuickSetupResponse, …).
The generator writes a placeholder module path
(github.com/GIT_USER_ID/GIT_REPO_ID). Edit the first line of
go-client/go.mod to your real module path (below it is example.com/phosra) so
you can import it.
2
Call the sandbox
go
package mainimport ( "context" "fmt" "log" phosra "example.com/phosra")func main() { cfg := phosra.NewConfiguration() // Point the default server at the open sandbox. cfg.Servers[0].URL = "https://phosra-api-sandbox-production.up.railway.app/api/v1" client := phosra.NewAPIClient(cfg) req := phosra.NewQuickSetupRequest("Emma", "2016-03-15") req.SetStrictness("recommended") resp, _, err := client.QuickSetupAPI.SetupQuickPost(context.Background()). QuickSetupRequest(*req).Execute() if err != nil { log.Fatal(err) } family := resp.GetFamily() summary := resp.GetRuleSummary() fmt.Println("family:", family.GetName()) fmt.Println("age_group:", resp.GetAgeGroup()) fmt.Println("rules_enabled:", summary.GetTotalRulesEnabled())}
Other common targets: -g csharp, -g rust, -g kotlin, -g php, -g ruby,
-g swift5. List every generator with
npx @openapitools/openapi-generator-cli list.
Authenticating a generated client
The verified calls above hit the open sandboxPOST /setup/quick, which needs no
key — that is the sandbox-first path. Real product routes live under /developer/* and
need a phosra_test_ (sandbox) or phosra_live_ (production) key sent as
Authorization: Bearer. Wire it into the generated client's config:
If you generate from openapi.data-plane.yaml, be aware that those endpoints are
not plain REST:
A generated client gives you the correct wire shapes for the data plane, but it
will not produce valid requests on its own. Profile GETs are RFC 9421-signed
by the resolver, binding POSTs require an accredited caller signature, and
profile responses are root-verifiable signed documents. Signing and verification
are cryptographic steps the generator does not emit.
For anything on the data plane, use the maintained SDKs that implement the signing:
@phosra/gatekeeper — the
platform-side decision engine that drives the data plane end-to-end (verify profiles,
enforce, send §8.3.8 receipts).
Use a generated data-plane client only for reading response types into your own models,
not for making the signed calls. The product API (openapi.yaml) has no such
caveat — a generated client calls it directly, as shown above.
Pin your generator version
Generators evolve; output can shift between major versions. For reproducible builds,
pin the exact version instead of letting npx pull latest:
bash
# Pin openapi-generatornpx @openapitools/[email protected] generate ... # CLI wrapper# (the wrapper then downloads generator engine 7.23.0 — pin it in openapitools.json)# Pin openapi-typescriptnpx[email protected] ...
The spec is versioned by the /api/v1 path and evolves additively (see
Versioning). Re-run the generator after a spec change to pick up new
fields; a regeneration never silently changes an existing field's type without a
version bump.