Skip to main content
This is the whole journey a family takes through Phosra, start to finish, on a single page. You will create a family, browse the platform catalog, link two platforms, unlink one of them, watch the other survive untouched, and relink the first — all against the public sandbox. Every request and response below is verbatim live output, captured while writing this page by running these exact calls against https://phosra-api-sandbox-production.up.railway.app. No API key, nothing to install.
Sandbox-first. These calls run against the open partner sandbox with no credential. Nothing you create touches a real family. The shapes are identical in production — you swap the base URL for https://prodapi.phosra.com and authenticate with a phosra_live_… key.
There is one interactive path — the OAuth connect ceremony — where a real parent approves in a browser. Its consent page belongs to the sandbox reference provider and ships its own fixed demo profiles:
Phosra sandbox consent page titled 'Connect your family to this app?' with a 'Sandbox reference provider' tag, listing the reference provider's built-in demo child profiles Mia, Leo, and Ava, and Approve / Deny buttons.

The ten phases

1

Create the family

2

Browse the catalog

3

Link the first platform (Notflix)

4

Confirm the link

5

Link a second platform (Pixagram)

6

See both managed

7

Unlink Notflix

8

Confirm release — and isolation

9

The survivor is untouched

10

Relink Notflix

The load-bearing idea is phases 7–9: unlinking one platform is scoped to that link alone. Deleting the Notflix link does not disturb the second link, and that platform keeps verifying. There is no cross-service bleed.

The same journey, in a real app

Before the raw API calls, here is what the ten phases look like to a family. Every screen below is a real screenshot captured from Propagate — a reference parental-control app built on this exact sandbox API — and from a platform’s own website. Nothing is mocked or drawn.
One cast, two names. The screenshots and the code below follow the same child and the same streaming link — only Propagate’s playful brand names differ from the public catalog’s real platform ids. Follow the code and you land on the exact UI state each frame shows.
In the screenshots (Propagate)In the API calls belowThe bridge
Ruby, the childchild_name: "Ruby"The same child, end to end.
Notflix (streaming)platform_id: "netflix"Notflix is Propagate’s stand-in brand for the catalog’s Netflix — same streaming service, same link/unlink/relink target.
Pixagram (a second service)platform_id: "xbox"Pixagram is a social app. The public catalog ships real platform ids and has no social equivalent, so the API links xbox (a gaming platform) as the second, unrelated service. Both prove the identical point: unlink one, the other survives.
1

Create the family

The family lives in the app: two children (Ruby, Mateo) and the parent as owner. This guide’s API path provisions Ruby — the child every later frame follows. This is the POST /setup/quick result — a family plus a child plus a starter policy — rendered for a human.
Propagate iOS Family screen. A KIDS section lists Ruby ('Relaxed — a little above age 8') and Mateo ('Content suited to age 11'), each with an initial avatar. A PARENTS section shows the signed-in parent tagged 'You' and 'Owner', with 'Invite co-parent' and 'Join a family with a code' actions. A bottom tab bar has Home, Family (selected), Services, Settings.
2

Browse the catalog

The catalog of connectable services, grouped by category. GET /platforms returns this list.
Propagate 'Add a service' catalog. SOCIAL lists Snaptr and Pixagram; STREAMING lists Notflix with a green checkmark 'Enforced' badge left over from a prior session; GAMING lists Bloxby. Each row has an icon, a one-line description of what it locks down, and a chevron.
3

Link the first platform (Notflix)

The link ceremony — the app-side equivalent of POST /compliance against platform_id: "netflix". It states, up front, exactly which rules the platform will apply and confirm before anything turns green.
Propagate 'Connect Notflix' screen with a 'phosra · OCSS' header. A card titled 'APPLIED & VERIFIED ON NOTFLIX' lists four rules with checkmarks: cap maturity rating for the child's profile, block specific titles by ID, lock the child into a kids profile, disable autoplay of the next episode. A green 'Continue' button sits at the bottom above the disclaimer about never showing a fake green.
4

Confirm the link

The link’s detail screen. This is the status: "verified" from the compliance response, shown as a family sees it: Enforced, connected today, last synced just now.
Propagate Notflix detail screen. A green shield 'Enforced' card reads 'Applied and verified via secure OAuth — settings are written and confirmed through Notflix's API.' A Status section shows Protection type: Enforced, Connected: July 5 2026, Last sync: 'Applied & verified just now'. An Applied Rules section lists the maturity-cap, block-titles, and kids-profile-lock rules with green checkmarks.
5

Link a second platform (Pixagram)

A second service — Pixagram, a social app — is linked. The Services dashboard now reads 2 of 2 enforced, the two-managed-platforms state the second POST /compliance produces. (In the API calls this second service is xbox: the catalog has no social equivalent for Pixagram, so xbox stands in — see the cast note above.)
Propagate Services screen. A purple 'Services to Protect' header card reads '2 / 2' with a '2 ENFORCED' pill and a full green progress bar. Below, a SET UP list shows Notflix (Enforced, 4 rules applied) and Pixagram (Enforced, 4 rules applied), each 'Applied & verified just now', plus an 'Add a service' button.
6

See it enforced on the platform

Proof that the link is not cosmetic: Ruby’s profile on the streaming platform’s own website carries a Managed via Phosra badge. The rule is enforced where it actually matters.
The Notflix web app 'Manage profile and preferences' page in dark mode, signed in as ruby-family-f5@example.com. Ruby's profile row — labeled 'Kids profile · age 17', the reference sandbox's demo default — carries a green 'Managed via Phosra' badge. A PREFERENCES section lists Languages, Adjust Parental Controls, Subtitle appearance, and Playback settings.
7

Unlink one platform

The family cancels one service. The confirmation is scoped and explicit — it will revoke only this platform’s rules. This is the app-side DELETE /compliance/{linkID} for the Notflix link.
Propagate Notflix detail screen with a 'Disconnect Notflix?' confirmation dialog: 'We'll remove this connection and revoke the rules applied to Notflix.' with Cancel and red Disconnect buttons. Behind it, a 'Children on Notflix' section lists Ruby ('4 rules applied') with a Remove action and the note 'Removing one child revokes only their rules — the others stay connected.'
8

Confirm release

The unlinked platform reports Disconnected — rules are no longer applied, and the platform itself confirmed the removal. Clean teardown, not a silent drop. A Reconnect button waits.
Propagate Notflix detail screen showing a teal 'Enforceable' capability card and a 'Disconnected' status card: 'Rules are no longer applied via Phosra. Notflix confirmed removal · July 5, 2026.' A large green 'Reconnect' button sits below with the caption 'Reconnect to re-apply Phosra rules on Notflix.'
9

The other platform survived

The isolation guarantee, made visible: after unlinking one service, the dashboard reads 1 of 1 enforced — the other platform is untouched and still verifying. No cross-service bleed. (In the screenshots the survivor is Pixagram; in the API calls it is xbox — the same second, unrelated service standing in for Pixagram, see the cast note above.)
Propagate Services screen after unlinking Notflix. The 'Services to Protect' header now reads '1 / 1' with a '1 ENFORCED' pill and a full green bar. The SET UP list shows only Pixagram (Enforced, 4 rules applied, 'Applied & verified just now'), plus an 'Add a service' button.
10

Relink

The family resubscribes and relinks. The platform confirms and protection resumes on a fresh link — the app-side POST /compliance for netflix again, closing the loop.
Propagate success screen with a large green shield checkmark. Headline 'Notflix connected', subtext 'Protecting Ruby', timestamp 'Jul 5 at 10:07 PM', and a green 'Done' button.
Those are the ten phases as a family experiences them. The rest of this page is the same ten phases as API calls — every request and response run live against the sandbox, following the same child (Ruby) and the same streaming link (Notflixnetflix).

Before you start

Set the base URL once so every step is copy-paste:
export PHOSRA_BASE="https://phosra-api-sandbox-production.up.railway.app"
This guide uses the direct compliance link — the simplest full-lifecycle path, where you present a platform credential to Phosra. For the interactive OAuth connect ceremony (the consent page above, with authorize_urltokenprofiles), see Connect a platform. The link/unlink/relink lifecycle below is the same either way.
1

Create the family

One call onboards a family, a child, and an age-appropriate starter policy. setup/quick needs only a child name and birth date. We create Ruby — the same child the screenshots follow (Phase 1).
curl -s -X POST "$PHOSRA_BASE/api/v1/setup/quick" \
  -H "Content-Type: application/json" \
  -d '{
    "child_name": "Ruby",
    "birth_date": "2018-02-14",
    "family_name": "Ruby'\''s Family",
    "strictness": "relaxed"
  }'
The response returns the family, the child, and a fully-populated starter policy (20 rules seeded from the relaxed preset for an 8-year-old, with the content cap at PG / 7+). Truncated to the parts you carry forward:
{
  "family": {
    "id": "07617e71-c05d-48a8-942b-53c06b04a2db",
    "name": "Ruby's Family",
    "created_at": "2026-07-06T09:02:10.028096913Z"
  },
  "child": {
    "id": "5d8d11cb-a5c7-4598-8972-85ef1f248350",
    "family_id": "07617e71-c05d-48a8-942b-53c06b04a2db",
    "name": "Ruby",
    "birth_date": "2018-02-14T00:00:00Z"
  },
  "policy": {
    "id": "c9cfef3c-c556-4b58-bab5-e6f4fcb3ee36",
    "name": "Ruby's Protection Policy",
    "status": "active"
  },
  "rule_summary": {
    "total_rules_enabled": 20,
    "content_rating": "PG",
    "web_filter_level": "strict",
    "screen_time_minutes": 117
  }
}
Keep family.id — every remaining step is scoped to it.
export FAMILY_ID="07617e71-c05d-48a8-942b-53c06b04a2db"
FieldTypeNotes
child_namestringRequired. The child’s display name.
birth_datedateRequired. YYYY-MM-DD. Drives the age-appropriate rule preset.
family_namestringOptional. Defaults to "{child_name}'s Family".
strictnessenumrecommended (default), strict, or relaxed.
A missing child_name or birth_date returns 400 { "message": "child_name is required" }. Re-running with the same (family, child_name, birth_date) de-dupes rather than creating a duplicate child.
2

Browse the catalog

GET /platforms returns everything a family can connect — streaming apps, game consoles, DNS filters, devices, operating systems. No auth.
curl -s "$PHOSRA_BASE/api/v1/platforms"
The live sandbox returns 22 platforms. Two of them — netflix (the streaming service the screenshots brand Notflix) and xbox (the second, unrelated service) — are what we link next:
[
  { "id": "netflix", "name": "Netflix", "category": "streaming", "enabled": true },
  { "id": "xbox",    "name": "Xbox",    "category": "gaming",    "enabled": true }
]
3

Link Notflix (netflix)

Linking is a single POST /compliance with the family, the platform, and a platform credential. In the sandbox the credential is a demo token; in production it is the real access token you obtained from the connect ceremony. This is the API form of the link ceremony in Phase 3.
curl -s -X POST "$PHOSRA_BASE/api/v1/compliance" \
  -H "Content-Type: application/json" \
  -d "{
    \"family_id\": \"$FAMILY_ID\",
    \"platform_id\": \"netflix\",
    \"credentials\": \"sandbox-demo-token\"
  }"
The response is the new link. It comes back verified — Phosra confirmed the credential against the platform. This is the exact state Phase 4 renders as Enforced · Applied & verified just now:
{
  "id": "5b6d14f3-3ea5-4ae0-a98e-baced770d1df",
  "family_id": "07617e71-c05d-48a8-942b-53c06b04a2db",
  "platform_id": "netflix",
  "status": "verified",
  "verified_at": "2026-07-06T09:02:28.396962605Z"
}
export NETFLIX_LINK_ID="5b6d14f3-3ea5-4ae0-a98e-baced770d1df"
FieldTypeNotes
family_iduuidRequired. From step 1.
platform_idstringRequired. A catalog id from step 2 (e.g. netflix).
credentialsstringRequired. Sandbox: any demo token. Production: the platform access token.
An unknown platform_id or malformed family_id returns 400. A duplicate active link for the same (family, platform) returns the existing link rather than a second row.
4

Confirm the link

GET /families/{id}/compliance lists every active link for the family. Right now there is one:
curl -s "$PHOSRA_BASE/api/v1/families/$FAMILY_ID/compliance"
[
  {
    "id": "5b6d14f3-3ea5-4ae0-a98e-baced770d1df",
    "family_id": "07617e71-c05d-48a8-942b-53c06b04a2db",
    "platform_id": "netflix",
    "status": "verified",
    "verified_at": "2026-07-06T09:02:28.396962Z"
  }
]
5

Link the second service (xbox)

Repeat the link for a second, unrelated platform. The screenshots show this as a second service (Pixagram, a social app) reaching 2 of 2 enforced in Phase 5; the public catalog has no social equivalent for Pixagram, so the API links xbox — same call, different platform_id.
curl -s -X POST "$PHOSRA_BASE/api/v1/compliance" \
  -H "Content-Type: application/json" \
  -d "{
    \"family_id\": \"$FAMILY_ID\",
    \"platform_id\": \"xbox\",
    \"credentials\": \"sandbox-demo-token\"
  }"
{
  "id": "96d4b117-7711-4527-9c4a-e6e13b7094ff",
  "family_id": "07617e71-c05d-48a8-942b-53c06b04a2db",
  "platform_id": "xbox",
  "status": "verified",
  "verified_at": "2026-07-06T09:02:28.913726803Z"
}
export XBOX_LINK_ID="96d4b117-7711-4527-9c4a-e6e13b7094ff"
6

See both managed

The family now manages two verified links — the 2/2 enforced dashboard state of Phase 5. The same list call returns both:
curl -s "$PHOSRA_BASE/api/v1/families/$FAMILY_ID/compliance"
[
  {
    "id": "5b6d14f3-3ea5-4ae0-a98e-baced770d1df",
    "platform_id": "netflix",
    "status": "verified",
    "verified_at": "2026-07-06T09:02:28.396962Z"
  },
  {
    "id": "96d4b117-7711-4527-9c4a-e6e13b7094ff",
    "platform_id": "xbox",
    "status": "verified",
    "verified_at": "2026-07-06T09:02:28.913726Z"
  }
]
7

Unlink Notflix (netflix)

The family cancels Notflix — the Phase 7 “Disconnect Notflix?” dialog. Delete only the Netflix link by its linkID. A successful teardown returns 204 No Content — no body.
curl -s -o /dev/null -w "%{http_code}\n" \
  -X DELETE "$PHOSRA_BASE/api/v1/compliance/$NETFLIX_LINK_ID"
# → 204
HTTP/1.1 204 No Content
The delete is keyed on the link’s id, not the platform or the family. It removes exactly one link. This is what makes the next step true.
8

Confirm release — and isolation

List the family’s links again. Netflix is gone; the xbox link is untouched — the 1/1 enforced survivor state of Phase 9:
curl -s "$PHOSRA_BASE/api/v1/families/$FAMILY_ID/compliance"
[
  {
    "id": "96d4b117-7711-4527-9c4a-e6e13b7094ff",
    "family_id": "07617e71-c05d-48a8-942b-53c06b04a2db",
    "platform_id": "xbox",
    "status": "verified",
    "verified_at": "2026-07-06T09:02:28.913726Z"
  }
]
Two-lane timeline. The Netflix lane runs verified through link, second-link, and managed, is cut at 'unlink Netflix' (DELETE 204), shows 'released', then a new verified node at relink. The Xbox lane runs continuously verified across every phase, labeled 'unaffected, still verified'.
9

The survivor survived (xbox)

Isolation is not just “the xbox link is still listed” — it is “it still works.” Verify the Xbox link after the Netflix teardown and it re-confirms clean:
curl -s -X POST "$PHOSRA_BASE/api/v1/compliance/$XBOX_LINK_ID/verify" \
  -H "Content-Type: application/json" -d '{}'
{ "status": "verified" }
Removing Netflix had zero effect on the Xbox link — a different platform’s enforcement kept running the whole time. This is the guarantee real households depend on: cancelling one service never quietly drops protection on another.
10

Relink Notflix (netflix)

The family resubscribes — the Phase 10 “Notflix connected · Protecting Ruby” success screen. Relinking is just the link call again — and because the earlier delete fully released the old link, you get a fresh linkID (note it differs from step 3):
curl -s -X POST "$PHOSRA_BASE/api/v1/compliance" \
  -H "Content-Type: application/json" \
  -d "{
    \"family_id\": \"$FAMILY_ID\",
    \"platform_id\": \"netflix\",
    \"credentials\": \"sandbox-demo-token\"
  }"
{
  "id": "28163206-1de7-4d76-b40b-302a5296846b",
  "family_id": "07617e71-c05d-48a8-942b-53c06b04a2db",
  "platform_id": "netflix",
  "status": "verified",
  "verified_at": "2026-07-06T09:02:30.111746394Z"
}
The family is back to two managed platforms, with Netflix on a new link (28163206…, up from the released 5b6d14f3…) and Xbox on the same one it has had the entire time.

The whole flow at a glance

Every row below is one call you just ran, in order — the same Ruby family the screenshots follow:
#PhaseCallLive result
1Create the familyPOST /setup/quickfamily 07617e71…, child Ruby, 20-rule policy
2Browse the catalogGET /platforms22 connectable platforms
3Link Notflix (netflix)POST /compliancelink 5b6d14f3…, verified
4Confirm the linkGET /families/{id}/compliance[netflix]
5Link second (xbox)POST /compliancelink 96d4b117…, verified
6See both managedGET /families/{id}/compliance[netflix, xbox]
7Unlink NotflixDELETE /compliance/{linkID}204 No Content
8Confirm releaseGET /families/{id}/compliance[xbox] — Netflix gone
9Survivor survivedPOST /compliance/{linkID}/verify{ "status": "verified" }
10Relink NotflixPOST /compliancenew link 28163206…, verified

Next steps

Connect a platform

The interactive OAuth connect ceremony behind the consent page — authorize_url → token → profiles.

Disconnect & reconnect

The decline path, the production teardown, and clean re-approval in depth.

Families & kids

Manage children, policies, and rules on the family you just created.

Test in the sandbox

The seeded reference providers and Trust List these calls run against.