Status: Draft v0.1.0 — This section is informative. It is explicitly non-normative and illustrative.
This document sketches how a system could expose Rights Layer expressions through a resource-oriented interface. It exists only to make the Data Model tangible.
This draft imposes no requirements. Any protocol may be used — or none. Conformance to Rights Layer is defined only over expressions (Data Model, section 5), never over APIs. A system that exchanges conforming expressions by file transfer, message queue, removable media, or paper is exactly as conformant as one that implements every operation below. No specific protocol, transport, serialization framework, or product is assumed or required (Principle P1 in Core Principles).
The interface is also purely descriptive, like the layer itself (Principle P7): the operations below record and retrieve expressions. Whether a caller is authenticated, whether a request is authorized, and whether a Decision is enforced are matters for the deployment, addressed by mechanisms of its choice (an authentication mechanism, an authorization mechanism, transport security — see Security Considerations).
The operations are defined protocol-neutrally. Each takes and returns entities of the Data Model; “returns” means returning a Rights Layer expression (or fragment) containing the named entities.
id (URI) of a Right.sourceRefs and eventRefs
intact.status property, if present, is informative; normative
state is derived from the Event history (see GetEvents).subjectRef is that Subject, as known to
this system. A directory returns what it has aggregated; a system of
record returns what it grounds. No system is presumed to know all Rights
of a Subject.aboutRef),
and optionally a since timestamp (RFC 3339).occurredAt, restricted to those with occurredAt (or recordedAt, at
the deployment’s documented choice) after since if given.since-based retrieval allows
incremental consumption without re-reading history.id of a newly recorded ExerciseRequested Event.SubmitEligibilityResponse); whether a Decision was established is read
separately (see GetDecision).id (URI) of an Eligibility, and an Eligibility Response
entity — value (Boolean), issuerRef, issuedAt, proof, and
optionally evidenceRefs.id of the recorded Response, and the id of the
corresponding EligibilityResponseIssued Event.response
property, preserving the one-to-one binding. A Response whose
authenticity or integrity cannot be verified, per the deployment’s own
mechanisms, is a matter for the deployment to reject or flag — the layer
prescribes no mechanism.id of an ExerciseRequested Event.requestRef is that Event
— with actionRef, rightRef, responseRefs, establishedBy, and
establishedAt — or nothing. Absence of a Decision means no Decision has
been established: one or more Eligibilities are unanswered, or some
Response is false. There is no permit, deny, or indeterminate
result, and no negative Decision.eventType
(ExerciseStarted or ExerciseEnded), when it occurred, and optionally
the actor, event payload, and a Proof Reference.id of the newly recorded Exercise Event.One possible mapping — again, illustrative only — onto plain HTTP with the canonical JSON serialization:
| Abstract operation | HTTP mapping |
|---|---|
| GetRight(id) | GET /rights/{id} |
| ListRightsBySubject(subjectRef) | GET /rights?subject={subjectRef} |
| GetEvents(aboutRef, since) | GET /events?about={aboutRef}&since={timestamp} |
| RequestExercise(rightRef, actionRef) | POST /exercise-requests |
| SubmitEligibilityResponse(eligibilityRef, response) | POST /eligibilities/{id}/response |
| GetDecision(requestRef) | GET /decisions?request={requestRef} |
| RecordExerciseEvent(…) | POST /exercises/{id}/events |
Identifiers are URIs and would be URL-encoded where they appear in paths or query strings. Error handling, pagination, content negotiation, versioning, and transport security are deliberately unspecified here — a real deployment would define them with mechanisms of its choice.
Using the data of the driving licence example: Alice requests to exercise the drive Action of her driving licence Right.
Request:
POST /exercise-requests
Content-Type: application/json
{
"rightRef": "urn:example:right:alice-driving-licence",
"actionRef": "urn:example:action:drive-ordinary"
}
Response — the recorded ExerciseRequested Event:
HTTP/1.1 201 Created
{
"@context": "https://rights-layer.org/ns/v0",
"type": "RightsExpression",
"specVersion": "0.1.0",
"entities": [
{
"id": "urn:example:event:exercise-request-1",
"type": ["Event", "ExerciseEvent"],
"eventType": "ExerciseRequested",
"aboutRef": "urn:example:exercise:drive-2026-07-01",
"actorRef": "urn:example:subject:alice",
"occurredAt": "2026-07-01T07:59:00+09:00"
}
]
}
The licensing authority — a Response issuer, entirely outside the layer —
has evaluated the requirement of the Eligibility
urn:example:eligibility:licence-valid and presents its Boolean answer:
POST /eligibilities/urn%3Aexample%3Aeligibility%3Alicence-valid/response
Content-Type: application/json
{
"id": "urn:example:response:licence-valid-2026-07-01",
"type": "EligibilityResponse",
"value": true,
"issuerRef": "urn:example:authority:public-safety-commission",
"issuedAt": "2026-07-01T08:00:00+09:00",
"proof": {
"type": "ProofReference",
"proofKind": "registry-lookup",
"reference": "urn:example:licence-register:attestation:7c1"
},
"evidenceRefs": ["urn:example:evidence:licence-record-check"]
}
Response — the recorded EligibilityResponseIssued Event:
HTTP/1.1 201 Created
{
"@context": "https://rights-layer.org/ns/v0",
"type": "RightsExpression",
"specVersion": "0.1.0",
"entities": [
{
"id": "urn:example:event:response-issued-1",
"type": "Event",
"eventType": "EligibilityResponseIssued",
"aboutRef": "urn:example:eligibility:licence-valid",
"actorRef": "urn:example:authority:public-safety-commission",
"occurredAt": "2026-07-01T08:00:00+09:00",
"data": { "responseRef": "urn:example:response:licence-valid-2026-07-01", "value": true }
}
]
}
The second Eligibility of the Action
(urn:example:eligibility:conditions-met) receives its own Response from
its own issuer in the same way. Each Response answers exactly one
Eligibility.
Request:
GET /decisions?request=urn%3Aexample%3Aevent%3Aexercise-request-1
Response — both Eligibilities of the Action have exactly one verifiable
Response and both are true, so a Decision was established:
HTTP/1.1 200 OK
{
"@context": "https://rights-layer.org/ns/v0",
"type": "RightsExpression",
"specVersion": "0.1.0",
"entities": [
{
"id": "urn:example:decision:drive-2026-07-01",
"type": "Decision",
"actionRef": "urn:example:action:drive-ordinary",
"rightRef": "urn:example:right:alice-driving-licence",
"responseRefs": [
"urn:example:response:licence-valid-2026-07-01",
"urn:example:response:conditions-met-2026-07-01"
],
"requestRef": "urn:example:event:exercise-request-1",
"establishedAt": "2026-07-01T08:00:01+09:00"
}
]
}
If any Eligibility were unanswered, or any Response were false, no
Decision would exist and this request would return nothing (for example, an
empty expression or a not-found status — the deployment’s choice). Absence
of a Decision means only that it is not established; there is no negative
Decision to retrieve.
A consumer that wants more than the claim follows the Decision’s
responseRefs to each Eligibility Response, each Response’s proof to the
issuer’s verification mechanism, and each Response’s evidenceRefs to the
Evidence, its evidenceSourceRef to the Evidence Source, and its Proof
Reference to the verification mechanism the governing system provides (see
Architecture, section 3, and
Security Considerations).
To restate: nothing in this document is required. It is one way, among arbitrarily many, to expose expressions. Deployments may expose fewer operations, more operations, different operations, or no operations at all. The only conformance target in Rights Layer v0.1.0 is the expression itself.