Developer documentation
Steady North Decision API
Authenticate with an organization API key: Authorization: Bearer sn_sbx_…. Keys are created in the dashboard, scoped, and shown once. Every decision returns a receipt id; receipts are independently verifiable. This demo environment ships a seeded key for the Lakeshore demo org so the examples below work as-is:
sn_sbx_2f7c9a41d8e3b6055f1a4c2d9b8e7f60a3c1d5b2
POST/api/v1/evaluatescope: certbridge:write | agebridge:evaluate
The generic decision endpoint — module, subject, jurisdictions, normalized context, and evidence in; decision, requirements, missing evidence, and receipt out.
curl -s http://localhost:3960/api/v1/evaluate \
-H "Authorization: Bearer sn_sbx_2f7c9a41d8e3b6055f1a4c2d9b8e7f60a3c1d5b2" \
-H "content-type: application/json" \
-d '{
"module": "CERTBRIDGE",
"subjectLabel": "Sample imported toy",
"jurisdictions": ["US"],
"context": { "product": { "category": "TOY", "isChildrensProduct": true,
"imported": true, "recallStatus": "NONE" } },
"evidence": [
{ "key": "field:manufacturer_name", "value": "Acme Toys" },
{ "key": "citations:present", "value": "ASTM F963-23" }
]
}'POST/api/v1/age/evaluatescope: agebridge:evaluate
AgeBridge wrapper — speak in app terms. Age signals are ranges, never birth dates. The example uses an inline app; registered apps pass appId.
curl -s http://localhost:3960/api/v1/age/evaluate \
-H "Authorization: Bearer <loopline key>" \
-H "content-type: application/json" \
-d '{
"app": { "name": "MyApp", "category": "SOCIAL", "minorsAllowed": true },
"platform": "IOS",
"jurisdictions": ["US", "US-TX"],
"feature": { "key": "DIRECT_MESSAGING", "capabilities": ["MESSAGING","SOCIAL"] },
"ageSignal": "13_15",
"parentApprovalState": "NOT_REQUESTED"
}'
→ { "decision": "REQUIRE_PARENT_APPROVAL", "rules": [...], "receiptId": "SN-RCP-…" }GET/api/v1/receipts/{id}scope: receipts:read (org receipts)
Fetch a receipt with its canonical payload and a fresh verification. Receipts from the public checkers are readable without a key.
POST/api/v1/receipts/verify
Answers one question: has this record changed since it was issued?
curl -s http://localhost:3960/api/v1/receipts/verify \
-H "content-type: application/json" \
-d '{ "receiptId": "SN-RCP-XXXXXXXXXXXX" }'
→ { "valid": true, "checks": [
{ "name": "Payload hash", "ok": true },
{ "name": "Signature", "ok": true },
{ "name": "Receipt id embedded in payload", "ok": true } ] }—Webhooks
Register endpoints in the dashboard. Deliveries POST JSON with headers x-sn-event, x-sn-delivery, and x-sn-signature (t=…,v1=HMAC_SHA256(secret, `${t}.${body}`)). Failed deliveries retry with exponential backoff (1m → 64m, 5 attempts). Events: decision.created, decision.changed, filing.status_changed, recall.detected, parent_approval_required, product.action_required, rule.changed.
SDK surface (planned): AgeBridge Swift / Kotlin adapters normalize native platform signals (Apple declared age range, Google Play age signals) into the ageSignal vocabulary client-side, then call /v1/age/evaluate. Native calls are never faked from the server.