Skip to main content
Six objects carry every parental-controls integration, plus one more that lives on the enforcement path. This page is the map: how they nest, how many of each you get, what states they move through, and where each one’s field-by-field reference lives. Read it once and the rest of the API reference falls into place. Every shape below is taken directly from the OpenAPI spec — the same document that generates the SDKs and the API reference. Where a field is an enum, the allowed values are the real ones the census accepts.

The resource graph

Entity-relationship diagram: Family 1—many Child and 1—many FamilyMember; Child 1—many ChildPolicy; ChildPolicy 1—many PolicyRule and 1—many EnforcementJob; EnforcementJob 1—many EnforcementResult (one per platform); each PolicyRule compiles to a Verdict/CategoryEntry, which on confirm() produces an EnforcementReceipt.

The Phosra core object model. A Family owns Children and FamilyMembers; each Child owns ChildPolicies; each policy owns PolicyRules. Enforcing a policy creates an EnforcementJob that fans out to one EnforcementResult per platform. On the data plane, each rule compiles to a Verdict that the gatekeeper reads locally, and confirming it writes an EnforcementReceipt.

Read each edge as “one … has many …”:
Two planes, one graph. The green objects (Family → PolicyRule) and the blue objects (EnforcementJob, EnforcementResult) live in the control/product plane — normal REST resources you read and write with a phosra_ key. The violet Verdict and EnforcementReceipt live on the data plane: they are compiled into a signed profile and evaluated locally, in-process by the gatekeeper — there is no hosted POST /check. The rule_ref field is the thread that stitches a product-plane PolicyRule to its data-plane Verdict and back to a receipt.

Objects

Family — the household root

The top of the graph. Everything else hangs off a family, directly or transitively.
Family
Reference: Create a family · List families · concept → Families
The people who can manage a family. Distinct from Child.
FamilyMember
Reference: Add a member · List members
A profile within a family, keyed by birth date. Phosra derives the age group (and thus the age-appropriate rule defaults) from birth_date.
Child
Reference: Add a child · Get a child · Age ratings · concept → Children & Age Groups
The container a child’s rules live in. A child may own several; policies carry a lifecycle status and a priority for ordering.
ChildPolicy
Reference: Create a policy · Generate rules from age · Activate · Pause · concept → Policies & Rules
A single rule inside a policy: which OCSS category, whether it’s on, and its category-specific config. There are 123 categories — see the Rule Categories reference.
PolicyRule
Reference: List policy rules · Bulk upsert rules · Update a rule
Created when you enforce a policy. It fans out to every connected platform in parallel.
EnforcementJob
Reference: Trigger enforcement · List jobs · Job results · concept → Enforcement
One row per connected platform in a job. This is what you poll to verify enforcement — there is no push webhook on job completion.
EnforcementResult
Reference: Get job results · Retry a job
On the data plane, each active rule compiles into a CategoryEntry inside the signed §8.3.6 enforcement profile. The @phosra/gatekeeper SDK reads it with gk.isAllowed({ category })entirely locally, zero network — and returns a Verdict.
Verdict (CategoryEntry)
One field, two spellings. The wire/profile names this fail_mode with values open/closed; the gatekeeper SDK surfaces the same signal as failMode with allow/block. fail_mode:"closed"failMode:"block". See Platform integration.
Reference: Fetch profile · Platform integration · glossary → Verdict
After enforcing (or refusing) a verdict, the platform calls verdict.confirm(...), which signs and POSTs a §8.3.8 enforcement_result receipt. It is identity-free by construction — no child ref, device id, or user id. The inner body is exactly five fields.
EnforcementResultBody (signed inner body)
Reference: Submit confirmation · glossary → Receipt

Lifecycle & state

Three objects in the graph are state machines. Knowing the transitions saves you a class of “why isn’t this enforcing?” bugs.

ChildPolicy — draft → active → paused

draft

Created but not enforcing. Build up rules here. POST /policies starts a policy in draft unless you activate it.

active

The only status that enforces. POST /policies/{id}/activate. When a child has multiple active policies, priority (higher wins) breaks the tie.

paused

Temporarily off without deleting. POST /policies/{id}/pause. Re-activate any time.

EnforcementJob — pending → running → completed | failed | partial

1

pending → running

The job is created (202 Accepted) and begins fanning out to platforms.
2

completed

Every EnforcementResult succeeded.
3

partial

Some platforms applied, some didn’t — inspect rules_skipped / rules_failed per result. Common when a platform can’t express a category (manual_attested; see Platforms).
4

failed

The job as a whole failed. Retry it.

Verdict standing — allow · warn · block (fail-closed)

A verdict is not a stored row that transitions; it is recomputed locally on every isAllowed() call from the current signed profile. Its standing is one of allow, warn, or block. If the cached profile is missing or expired, a fail_mode: closed category resolves to block with rule_ref: null — enforcement never silently passes.
Do not call confirm() on a fail-closed verdict (rule_ref is null) — there is nothing to attest. The SDK throws RuleRefRequired. See Platform integration.

Prove the graph is live

The product-plane objects are served today. No key gives you a 401 (not a 404), which is the correct answer — the surface exists:
The data-plane objects (Verdict, EnforcementReceipt) are served by the census. The public sandbox census is live and serves the signed Trust List every profile verifies against:
On production the product-plane resources above require a phosra_ key (mint one in the Developer Console); see Authentication. On the open sandbox the product plane is keyless — the Quickstart’s POST /setup/quick creates your first family → child → policy → rule → enforcement job end to end with no credential at all (see Test in the sandbox).

Where to go next

Quickstart →

Create the whole graph in one POST /setup/quick call, then enforce it.

Architecture →

Why the product plane and the enforcement data plane are kept separate.

Policies & Rules →

How the 123 OCSS categories become a policy.

Enforcement →

Jobs, per-platform results, and the poll-don’t-webhook contract.