Sandbox-first. These requests run against
https://phosra-api-sandbox-production.up.railway.app — open, seeded, and safe. In production,
change the base URL to https://prodapi.phosra.com and add your phosra_live_… key; the
request shapes are identical.Before you start
Create a family, a child, and an active policy — in one call
POST /setup/quick is the fastest path to a working policy. Give it a child’s name, birth
date, and a strictness level (recommended, strict, or light). Phosra derives the age
group from the birth date and returns a family, a child, an active policy, and a full set
of age-appropriate rules — with no follow-up calls.age_group: "preteen" from the 2016 birth date and mapped it to concrete rating
ceilings across five rating systems. Store family.id, child.id, and policy.id.Fields & errors — POST /setup/quick
Fields & errors — POST /setup/quick
Request body (
Response fields (200)
Errors
application/json)| Field | Type | Required | Description |
|---|---|---|---|
child_name | string | yes | The child’s display name; becomes child.name and seeds family.name ("Emma's Family"). |
birth_date | string (YYYY-MM-DD) | yes | Drives the derived age_group and the rating ceilings. |
strictness | string | no | One of recommended, strict, light. Defaults to recommended; an unrecognised value falls back to the default rather than erroring. |
| Field | Type | Description |
|---|---|---|
family.id | string (UUID) | The created family. Store it. |
child.id | string (UUID) | The child handle — pass it to /children/{id}/enforce and the policy endpoints. |
policy.id | string (UUID) | The generated policy. |
policy.status | string | active — the policy is live immediately, no activation call. |
age_group | string | Derived bucket, e.g. preteen, teen. |
max_ratings | object | Rating ceilings across mpaa, esrb, pegi, csm, tvpg. |
rule_summary.total_rules_enabled | integer | Count of enabled rule categories (20 for preteen / recommended). |
rules | array | One object per enabled rule category with its config (see next step). |
| Status | message | When it happens |
|---|---|---|
400 | child_name is required | child_name is missing from the body. |
400 | birth_date is required | birth_date is missing from the body. |
500 | internal server error | birth_date is present but not a parseable YYYY-MM-DD date. Validate the format client-side — the sandbox surfaces this as a 500 rather than a clean 400. |
Inspect the rules that were generated
The full response includes a Every category comes from the canonical rule reference. You can override
any of them later with the policy rules API.
rules array — one entry per enabled rule category, each with its
own config. For example, the addictive_design_control rule comes back pre-tuned:Fields — the rule object
Fields — the rule object
Each element of the
rules array:| Field | Type | Description |
|---|---|---|
id | string (UUID) | The rule’s id, for targeted updates. |
policy_id | string (UUID) | The policy this rule belongs to — matches policy.id. |
category | string | Rule category slug (e.g. addictive_design_control) from the rule reference. |
enabled | boolean | Whether the rule is active in this policy. |
config | object | Per-category settings. Shape depends on category. |
Enforce the policy across connected platforms
Push the active policy to every platform the family has connected. Enforcement is asynchronous —
you get a job back immediately (Real response (202):
202 Accepted):Fields & errors — POST /children/{childID}/enforce
Fields & errors — POST /children/{childID}/enforce
Path parameter
Response fields (202)
Errors
| Field | Type | Required | Description |
|---|---|---|---|
childID | string (UUID) | yes | The child.id from /setup/quick. |
| Field | Type | Description |
|---|---|---|
id | string (UUID) | The enforcement job id — poll it in the next step. |
child_id | string (UUID) | Echoes the child being enforced. |
policy_id | string (UUID) | The active policy being pushed. |
trigger_type | string | manual for a direct call. |
status | string | running at accept time. |
| Status | message | When it happens |
|---|---|---|
400 | invalid child ID | childID is not a well-formed UUID. |
404 | child not found | childID is a valid UUID but no such child exists. |
Confirm the job completed
Poll the job by id until Real response (200):That is the full loop: create → enforce → confirm. For results per platform, read
status is completed. Enforcement does not fire a webhook on
completion — poll the job, don’t wait for a callback.GET /enforcement/jobs/{id}/results — a non-empty manual_steps array means that platform is
parent-guided rather than programmatically applied.Fields & errors — GET /enforcement/jobs/{jobID}
Fields & errors — GET /enforcement/jobs/{jobID}
Path parameter
Response fields (200)
Notes & errors
| Field | Type | Required | Description |
|---|---|---|---|
jobID | string (UUID) | yes | The id returned by /enforce. |
| Field | Type | Description |
|---|---|---|
id | string (UUID) | The job id. |
status | string | running → completed (or failed). Poll until it leaves running. |
completed_at | string (RFC 3339) | When the job finished; absent while still running. |
| Behaviour | Detail |
|---|---|
Unknown jobID | Returns 200 with a null body rather than a 404. Treat null as “no such job” in your client. |
| No connected platforms | GET /enforcement/jobs/{id}/results returns null — there was nowhere to push. Connect a platform first (see Connect a platform). |
Adding more children
CallPOST /setup/quick once per child (each returns its own child in the same family when you
pass the same family context in production), or use the granular endpoints — POST /families,
POST /families/{familyID}/children, POST /children/{childID}/policies/generate — when you
need finer control. See the Families and
Children reference.
Next steps
Connect a platform
Link a family to a platform so enforcement has somewhere to land.
Test in the sandbox
Understand the open sandbox, the signed Trust List, and self-registration.