Issues a fresh §9.3(b) label for the binding identified by {id} (the binding_id from
the bind response). The prior label is invalidated
immediately — a subsequent profile GET on the old label returns 404. Only
endpoint_id_label is returned; the connect_secret is not rotated (it stays fixed per
binding).
Rotate on your window cadence to keep the bound-resolver label short-lived. Because rotation is
atomic and the old label dies instantly, poll the new label before discarding the old one only
if you cannot tolerate a single missed cycle.
Worked example
ts
import { signRequest } from "@openchildsafety/ocss"const BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1"const seed = new Uint8Array(Buffer.from(process.env.OCSS_SANDBOX_TEST_SEED_B64URL!, "base64url"))const keyID = process.env.OCSS_SANDBOX_KEY_ID!const bindingId = "c8ff82dd-4aa8-4a52-a235-ae13717eb4c8" // from the bind responseconst targetURI = `${BASE}/enforcement-endpoints/${bindingId}/rotate`const headers = signRequest({ method: "POST", targetURI, body: new TextEncoder().encode("{}"), keyID, seed, created: Math.floor(Date.now() / 1000) })headers["Content-Type"] = "application/json"const res = await fetch(targetURI, { method: "POST", headers, body: "{}" })console.log(res.status, await res.json())
The sign_request / SignRequest helper is defined once in the
request-signing guide — its Python, Go, and curl+openssl
recipes are verified against this sandbox. Even an empty-body POST covers content-digest
(over the bytes {}).
Example synthetic sandbox 200 response (credential redacted):