Skip to main content
GET
/
enforcement-profiles
/
{endpoint_id}
Signed curl (wire shape)
# Signed GET — headers are per-request (compute with the SDK, Node tab). No body.
curl https://phosra-api-sandbox-production.up.railway.app/api/v1/enforcement-profiles/iGrFqzp43O0S9YTNN2oAT6zMzcugEX_EwZbraWrE1AA \
  -H "OCSS-Spec-Version: OCSS-v1.0-pre" \
  -H 'Signature-Input: ocss=("@method" "@target-uri" "ocss-spec-version");created=1783315514;keyid="did:ocss:loopline#2026-06";alg="ed25519"' \
  -H 'Signature: ocss=:<base64-ed25519-sig>:'
{
  "document": "{\"categories\":[],\"document_type\":\"enforcement_profile\",\"ocss_version\":\"OCSS-v1.0-pre\",\"profile_ref\":\"sha256:898314e28cbd0e7bede49d8c48b6e4309ef019ff3189d03cae4215fe7b8d2b39\",\"rotation_epoch\":495369,\"token_binding\":\"9f4187aa0931973599d0178b0b6a219604206f4a48dcc6166edfb66468a21220\",\"window\":{\"not_after\":\"2026-07-06T10:00:00Z\",\"not_before\":\"2026-07-06T09:00:00Z\"}}",
  "key_id": "did:ocss:phosra-router#router-sandbox-2026-06",
  "alg": "ed25519",
  "sig": "stpRC97FNDiMd5JlkwTn_VxGJ3OngJ9opWiABfEZu4cof6ocL2aqIrjTDGH1vVUFmdI2m2TAhnMsT_Snz416Aw"
}
The core read of the data-plane. The {endpoint_id} path segment is the high-entropy bound-resolver label from the bind response, and presenting it under your RFC 9421 signature is the §9.3(b) authentication. The response is a SignedDocument whose document string parses to an EnforcementProfile.
document is a JSON string on the wire, not an object. The signature covers exactly those UTF-8 bytes — verify the signature over the raw string, then JSON.parse it. Never re-stringify an object before verifying. The canonical profile field is categories[]; profile.rules[] does not exist.
A wrong or unknown label returns 404, indistinguishable from a wrong-resolver dereference — fail-closed, no existence leak (§9.3(a)). The endpoint supports ETag / If-None-Match for 304 Not Modified.

Worked example

The @phosra/gatekeeper SDK is the supported path: it polls, verifies to the root, and exposes the decision. The raw signed GET is shown alongside it.
import { signRequest } from "@openchildsafety/ocss"

const BASE  = "https://phosra-api-sandbox-production.up.railway.app/api/v1"
const seed  = new Uint8Array(Buffer.from("bG9vcGxpbmUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE", "base64url"))
const keyID = "did:ocss:loopline#2026-06"

const label = "iGrFqzp43O0S9YTNN2oAT6zMzcugEX_EwZbraWrE1AA" // your endpoint_id_label
const targetURI = `${BASE}/enforcement-profiles/${label}`
const headers = signRequest({ method: "GET", targetURI, keyID, seed, created: Math.floor(Date.now() / 1000) })

const res = await fetch(targetURI, { method: "GET", headers })
const signed = await res.json()               // { document: "<json string>", key_id, alg, sig }
const profile = JSON.parse(signed.document)   // parse AFTER verifying the signature
console.log(res.status, profile.categories)
The signer is defined once in the request-signing guide. A GET covers only @method, @target-uri, and ocss-spec-versionno content-digest. Always verify signed.sig to the router key and root before you trust categories[].
Real 200 response (captured from the hosted sandbox — router-signed, categories[] empty here because the sandbox self-serve child carries no compiled rules yet):
{
  "document": "{\"categories\":[],\"document_type\":\"enforcement_profile\",\"ocss_version\":\"OCSS-v1.0-pre\",\"profile_ref\":\"sha256:0979812325e659675635dee167c202b92744891f315f99f1761a628e4ac3a87e\",\"rotation_epoch\":495365,\"token_binding\":\"162d45da4cd20908d138c08ae100439199953ed7810c88a149d162283268c605\",\"window\":{\"not_after\":\"2026-07-06T06:00:00Z\",\"not_before\":\"2026-07-06T05:00:00Z\"}}",
  "key_id": "did:ocss:phosra-router#router-sandbox-2026-06",
  "alg": "ed25519",
  "sig": "_GkUlEiLYL0T…"
}
Once the child has active rules (see the rule-write flow), each categories[] row carries a category, a decision (allow / warn / block), a fail_mode, and a per-child rule_ref you echo when you confirm enforcement.

Path Parameters

endpoint_id
string
required

The high-entropy §9.3(b) bound-resolver label returned by the mint endpoint. Treat as a secret credential — never log.

Response

Router-signed enforcement profile. Verify to root before trusting. categories[] is the canonical profile field.

Router-signed wrapper. document is a JSON STRING on the wire (not an object) whose UTF-8 contents are the canonical JCS bytes the router key signed. Verify with the resolved signing key over exactly those bytes — never by re-stringifying an object. Matches the Signed.MarshalJSON contract in internal/ocss/profile/document.go.

document
string
required

Canonical JSON string of the inner EnforcementProfile document. The signature covers exactly these UTF-8 bytes. Parse as JSON to obtain the EnforcementProfile; do not re-marshal before verifying.

key_id
string
required

D-15 key id in "did:ocss:#" form.

Example:

"did:ocss:phosra-router#router-sandbox-2026-06"

alg
enum<string>
required

One of: ed25519.

Available options:
ed25519
sig
string
required

base64url-raw (-_ alphabet, no padding) Ed25519 detached signature over the UTF-8 bytes of document. Matches base64.RawURLEncoding in internal/ocss/profile/document.go Sign().