Skip to main content
POST
/
sandbox
/
test-connect
Signed curl (wire shape)
# Signed headers are per-request — compute with the SDK (Node tab).
curl -X POST https://phosra-api-sandbox-production.up.railway.app/api/v1/sandbox/test-connect \
  -H "Content-Type: application/json" \
  -H "OCSS-Spec-Version: OCSS-v1.0-pre" \
  -H 'Signature-Input: ocss=("@method" "@target-uri" "ocss-spec-version" "content-digest");created=1783315514;keyid="did:ocss:loopline#2026-06";alg="ed25519"' \
  -H 'Signature: ocss=:<base64-ed25519-sig>:' \
  -H 'Content-Digest: sha-256=:<base64-sha256-of-body>:' \
  -d '{"platform_did":"did:ocss:loopline","webhook_url":"https://your-gatekeeper.example.com","connect_secret":"cs_your_hmac_secret"}'
{
  "binding_id": "22b577ea-4a53-4505-9eb5-541bf237cb42",
  "resolver_did": "did:ocss:loopline",
  "endpoint_id_label": "iWdlltz5F4sKbZKYgIvGkIJg7sylz2LN37cZUK8wiWY",
  "profile_url": "/api/v1/enforcement-profiles/iWdlltz5F4sKbZKYgIvGkIJg7sylz2LN37cZUK8wiWY",
  "connect_receiver": "https://loopline.example.com/api/ocss/connect",
  "delivered": false,
  "http_status": 0,
  "state": "sandbox-test-connect:22b577ea-4a53-4505-9eb5-541bf237cb42",
  "note": "callback delivery did not receive a 2xx — check webhook_url reachability and that connect_secret matches your gk.config; the binding is minted and profile_url is observable regardless"
}
Sandbox only. Gated on PHOSRA_ENV==sandbox — returns 404 on dev, staging, and production.
Runs the provider side of the EXT-04 §3.2 connect ceremony against your own platform DID + webhook, so a cold self-registered platform dev receives a real signed binding with no live counterparty and no roster edit. It mints a §9.3 binding for a seeded test child scoped to your platform_did and delivers the signed §3.6 callback to your webhook_url. The call is RFC 9421-signed as you. The binding is minted and profile_url is observable even if the webhook delivery leg failsdelivered=false with a note explaining why, but you can still poll the profile.

Worked example

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 targetURI = BASE + "/sandbox/test-connect"
const body = {
  platform_did:   "did:ocss:loopline",
  webhook_url:    "https://your-gatekeeper.example.com",   // POST /api/ocss/connect receiver base
  connect_secret: "cs_your_hmac_secret",                    // the secret you feed gk.config({ connectSecret })
}
const bodyText = JSON.stringify(body)
const headers = signRequest({ method: "POST", targetURI, body: new TextEncoder().encode(bodyText), keyID, seed, created: Math.floor(Date.now() / 1000) })
headers["Content-Type"] = "application/json"

const res = await fetch(targetURI, { method: "POST", headers, body: bodyText })
console.log(res.status, await res.json())
Real 200 response (captured — example.com returns 405 to the callback, so delivered=false; the binding is minted regardless):
{
  "binding_id": "145c2779-1759-4378-abf3-c49a49408ede",
  "resolver_did": "did:ocss:loopline",
  "endpoint_id_label": "ngb14RDrOQ57c9xIMPpKdQtqdLDdent9jiBo375He90",
  "profile_url": "/api/v1/enforcement-profiles/ngb14RDrOQ57c9xIMPpKdQtqdLDdent9jiBo375He90",
  "connect_receiver": "https://example.com/api/ocss/connect",
  "delivered": false,
  "http_status": 405,
  "state": "sandbox-test-connect:145c2779-1759-4378-abf3-c49a49408ede",
  "note": "callback delivery did not receive a 2xx — check webhook_url reachability and that connect_secret matches your gk.config; the binding is minted and profile_url is observable regardless"
}
Poll profile_url with your platform key (fetch profile) to see the router-signed profile land, and rotate with the returned binding_id.

Body

application/json

SANDBOX-ONLY (POST /api/v1/sandbox/test-connect). Runs the PROVIDER side of the EXT-04 §3.2 connect ceremony against the caller's own platform DID + webhook so a cold self-registered platform dev receives a real signed binding with no live counterparty. RFC 9421 signed as the caller. Source: sandboxTestConnectBody in internal/ocsshttp/handler_sandbox_test_connect.go.

platform_did
string
required

The consuming platform's Trust-List DID (the DID you self-registered and sign with).

Example:

"did:ocss:my-gatekeeper"

webhook_url
string
required

Your POST /api/ocss/connect receiver BASE (the well-known path is appended). Absolute http/https, no query/fragment/credentials. Plain http admitted (sandbox).

Example:

"https://my-gatekeeper.example.com"

connect_secret
string
required

The HMAC secret you fed into gk.config({ connectSecret }); the §3.6 callback is signed with it so your receiver verifies X-Phosra-Signature. Supplied because the census stores only its digest.

child_ref
string

Optional seeded test child ("child:"); defaults to the seeded Mia child.

Example:

"child:a11ce0fa-0000-4000-8000-0000000000a1"

window_seconds
integer<int64>

Optional §6.3 rotation window in seconds; defaults to 3600.

Response

Ceremony ran. The binding is minted and profile_url is observable even if the webhook leg failed (delivered=false + note).

Result of the sandbox provider ceremony. The binding is minted and profile_url is observable even when the webhook delivery leg fails (delivered=false + note). Source: sandboxTestConnectResp in handler_sandbox_test_connect.go.

binding_id
string<uuid>
required

The binding UUID returned once by the mint ceremony; pass it to the rotate endpoint.

resolver_did
string
required

Echo of platform_did — the DID the binding resolves to (sign the profile poll with it).

endpoint_id_label
string
required

The connect-ceremony binding label (unprefixed 43-char base64url). Poll it at profile_url with your platform key. Never log.

profile_url
string
required

Path to poll the router-signed enforcement profile for this binding.

Example:

"/api/v1/enforcement-profiles/…"

connect_receiver
string
required

The full receiver URL the signed §3.6 callback was POSTed to (webhook_url + /api/ocss/connect).

delivered
boolean
required

True when your receiver returned 2xx. False (with note) when the webhook leg failed — the binding is minted regardless.

http_status
integer
required

The HTTP status your receiver returned (0 if unreachable).

state
string
required

Opaque sandbox principal ref delivered alongside the label ("sandbox-test-connect:<binding_id>").

note
string

Present only when delivered=false — explains the webhook-leg failure.