Open standard · rights-receipt/1 · CC-BY-4.0
Rightshold Rights Receipt v1
Status: published, version rights-receipt/1 · Spec text: CC-BY-4.0 · JSON Schema: CC0-1.0 · Schema: https://www.rightshold.com/schemas/rights-receipt-v1.json
A Rights Receipt is a small signed statement that travels with one asset an agent ships — an image, font, dataset, code file or model. It says: these exact bytes (SHA-256), from this source, under this license, were checked for this intended use, with this verdict and these conditions, by an agent at this RS-KYA level, and the statement was recorded on a public ledger at this time. Anyone can verify it offline with the issuer's public key.
It answers the question every client, platform and reviewer asks about agent output: "Is this cleared to use, and can you prove it?"
1. Envelope
{
"receipt": { ...signed fields below... },
"signature": "<base64 Ed25519 signature>",
"kid": "key_…", "alg": "EdDSA",
"ledger": { "seq": 123, "commitment": "<hex>", "salt": "<hex>", "entry_url": "https://www.rightshold.com/v1/ledger/entries/123" }
}
2. Signed fields (receipt)
| Field | Meaning |
|---|---|
spec | Always rights-receipt/1 |
type | RightsReceipt |
id | rcpt_ + 20 hex |
issuer, kid | Issuer id and the JWKS key id that signed it |
issued_at, expires_at | RFC 3339; receipts expire (default 90 days, max 365) because licenses and evidence change |
asset | sha256 (required), kind (image, font, dataset, code, model, audio, video, text, other), name, media_type, source_url |
license | spdx_id, url, resource_id (a registered Rightshold resource) |
intended_use | The exact uses checked (commercial_use, model_training, redistribution, …) |
verdict | allowed · blocked · needs_review · insufficient_evidence |
conditions | duties (e.g. attribution), ready-to-paste attribution_text, unresolved questions |
agent | Issuing agent id, number and kya_level (RS-KYA L0–L5); L0 when no agent is named |
limitations | Plain-language scope |
3. Signature
Ed25519 over the UTF-8 bytes of the canonical JSON of receipt: object keys sorted lexicographically, no whitespace, values serialised as JSON. Look up kid in https://www.rightshold.com/.well-known/jwks.json (kty: OKP, crv: Ed25519). A key with status: retired only vouches for receipts issued before its retired_at.
const canon = (v) => v === null || typeof v !== "object" ? JSON.stringify(v)
: Array.isArray(v) ? "[" + v.map(canon).join(",") + "]"
: "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",") + "}";
4. Ledger inclusion
The ledger entry receipt.issued holds commitment = sha256("commit:" + canonical({opening: {receipt_sha256}, salt})), where receipt_sha256 = sha256(canonical(receipt)). Fetch entry_url for the entry and its Merkle inclusion proof against a signed block. This proves the receipt existed at that time without publishing its contents.
5. Verifying
1. Verify the signature (offline, §3). 2. Check spec and expires_at. 3. Hash the file you received and compare with asset.sha256. 4. Optionally check the ledger (§4), or call the free endpoint POST https://www.rightshold.com/v1/receipts/verify (or MCP verify_rights_receipt), which does all of it. 5. Treat verdict: allowed with its conditions as cleared; anything else is not.
6. Embedding conventions
| Where | Convention |
|---|---|
| Next to a file | Sidecar <filename>.rights.json containing the envelope (e.g. logo.png.rights.json) |
| HTTP response | Rights-Receipt: <https://www.rightshold.com/v1/receipts/rcpt_…>; rel="rights-receipt" or the same in a Link header |
| HTML page | <link rel="rights-receipt" href="https://www.rightshold.com/v1/receipts/rcpt_…"> (one per asset; add data-asset-sha256) |
| C2PA / Content Credentials | Custom assertion label com.rightshold.rights-receipt.v1 whose data is the envelope; asset.sha256 must match the C2PA hard binding. A model_training: blocked verdict maps to c2pa.training-mining notAllowed |
| package.json | "rightsReceipts": { "assets/logo.png": "assets/logo.png.rights.json" } |
| Model card (YAML front matter) | rights_receipts: list of receipt URLs or sidecar paths, one per training dataset / base model |
| Agent deliverable / MCP result | Include the envelope under rights_receipts[] next to the asset reference |
7. Issuing
POST https://www.rightshold.com/v1/receipts (API key) or MCP issue_rights_receipt:
{ "asset": { "sha256": "<hex>", "kind": "font", "name": "Inter.ttf" }, "license": "OFL-1.1",
"intended_use": { "commercial_use": true }, "agent": "<your handle or RS number>",
"attribution": { "title": "Inter", "author": "The Inter Project Authors" } }
Add ?quote=1 to get the price without issuing. Pricing: the decision is free; a signed receipt is in the "Signed rights manifest or Rights Receipt" line of https://www.rightshold.com/pricing (free allowance, then fractions of a cent). Verification is always free. For a whole deliverable with many inputs, use a rights manifest (POST /v1/manifests).
8. What a receipt is not
Not a license grant, not legal advice, and not a guarantee about facts outside the evidence it names. It is a signed, timestamped, verifiable record of what was checked and answered.
9. Versioning and license
Breaking changes get a new spec value (rights-receipt/2); verifiers must reject unknown major versions. Other issuers may implement this format; verifiers decide which issuers they trust. This text is licensed CC-BY-4.0; the JSON Schema is CC0-1.0.
