Skip to main content
This guide covers integrating Phosra into your application from scratch, including API key provisioning and your first enforcement run.
One auth header, everywhere. Every raw HTTP call on this page sends your key as Authorization: Bearer $PHOSRA_API_KEY — the one canonical form (X-Api-Key is accepted as an exact equivalent, but we use Bearer consistently so keys, WorkOS JWTs, and MCP tokens all share one header). Full detail: Authentication.

1. Create Your Account

Sign up at dashboard.phosra.com/signup via the WorkOS AuthKit hosted sign-up flow. There is no /auth/register endpoint on the Go API — account creation is handled by WorkOS. Once signed in, continue to step 2. (Full walkthrough: Create your account & get keys.)

2. Get an API Key

Use the developer console’s Keys page or call the API with your WorkOS session:
curl -X POST https://prodapi.phosra.com/api/v1/developers/orgs \
  -H "Authorization: Bearer <workos_access_token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Integration"}'

# Then create a key for the org:
curl -X POST https://prodapi.phosra.com/api/v1/developers/orgs/{orgId}/keys \
  -H "Authorization: Bearer <workos_access_token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "server-key", "scopes": ["read:families","write:policies","write:enforcement"]}'
The response includes the key once. Store it immediately:
# Production key
export PHOSRA_API_KEY="phosra_live_4a1b2c..."

# Sandbox key (use against https://phosra-api-sandbox-production.up.railway.app/api/v1)
export PHOSRA_API_KEY="phosra_test_4a1b2c..."
Key format: phosra_live_<64 hex chars> (production) or phosra_test_<64 hex chars> (sandbox). There is no _sk_ infix.

3. Use Quick Setup for Onboarding

The fastest path for your end users. When a parent signs up and adds their first child in your app, call the quick setup endpoint:
curl -X POST https://prodapi.phosra.com/api/v1/setup/quick \
  -H "Authorization: Bearer $PHOSRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "child_name": "Emma",
    "birth_date": "2016-03-15",
    "strictness": "recommended"
  }'
This returns a family, child, and an active policy with age-appropriate rules populated across the applicable rule categories for the requested strictness level, plus age_group, max_ratings, and rule_summary. Store the family.id and child.id for subsequent calls.
Prefer to try this without a key first? The Quickstart runs the exact same call against the open sandbox — no auth — and shows the real response.

4. Connect Platforms

For each platform the family uses, create a compliance link:
curl -X POST https://prodapi.phosra.com/api/v1/compliance \
  -H "Authorization: Bearer $PHOSRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "family_id": "FAMILY_UUID",
    "platform_id": "nextdns",
    "credentials": "nextdns-api-key"
  }'
List available platforms with GET /platforms to see what integrations are supported, and check each platform’s enforcement_mode — one of dns, device, or manual_attested. dns and device apply rules programmatically (a live DNS-provider write, or on-device via the Phosra app); manual_attested returns guided steps for the parent to attest. See Platforms & enforcement modes.

5. Register Webhooks

Set up webhooks to receive real-time event notifications (policy changes, new family members, etc.):
curl -X POST https://prodapi.phosra.com/api/v1/webhooks \
  -H "Authorization: Bearer $PHOSRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "family_id": "FAMILY_UUID",
    "url": "https://yourapp.com/webhooks/phosra",
    "events": ["policy.updated", "family.created"]
  }'
Note: webhooks do not fire on enforcement job completion. To verify enforcement results, poll GET /enforcement/jobs/{jobId}/results — see Enforcement.

6. Trigger Enforcement

Push the policy to all connected platforms, then poll the returned job for results:
BASE="https://prodapi.phosra.com/api/v1"
CHILD_ID="CHILD_UUID"   # from setup.child.id in step 3

# Trigger — returns a job (202 Accepted)
JOB_ID=$(curl -s -X POST "$BASE/children/$CHILD_ID/enforce" \
  -H "Authorization: Bearer $PHOSRA_API_KEY" | jq -r .id)

# Poll results
curl -s "$BASE/enforcement/jobs/$JOB_ID/results" \
  -H "Authorization: Bearer $PHOSRA_API_KEY"
A non-empty manual_steps array on any result means that platform is parent-guided, not programmatically applied.

Handle errors

Every failure returns a JSON envelope of the shape {"error", "message", "code"} (OCSS routes add class and, on standing checks, failed_step). Branch on code + class, never on the human-readable message. The full status/class matrix — every 4xx and 5xx, its cause, and its fix — is in the Errors reference. The one you will hit first while wiring auth:
CodeMeaningFix
401invalid API keyKey not in this environment’s store — a phosra_test_ key only works against the sandbox, phosra_live_ only against production.
403no API scopes in contextRequest reached a /developer/* route with no phosra_ key at all — attach Authorization: Bearer $PHOSRA_API_KEY.
403missing required scope: …Key authenticated but lacks the scope — mint a key with the scope named in the message.
429rate limitedWait until X-RateLimit-Reset, then retry.
500internal errorTransient — retry with exponential backoff.

Base URLs

EnvironmentBase URL
Productionhttps://prodapi.phosra.com/api/v1
Sandboxhttps://phosra-api-sandbox-production.up.railway.app/api/v1 — seeded demo family + phosra_test_ keys
Local devhttp://localhost:8080/api/v1
api.phosra.com has no DNS record — do not use it. Use prodapi.phosra.com for production. phosra-api.fly.dev is a legacy Fly.io address being decommissioned; use prodapi.phosra.com instead.

Checklist

  • Account created via WorkOS AuthKit
  • Developer org created and API key provisioned (test and production)
  • Quick setup tested with a sandbox child
  • At least one platform connected; enforcement_mode checked
  • Enforcement triggered and results polled (not webhook-waited)
  • Error handling implemented for 4xx and 5xx responses