Licensing Terms
Overview
Section titled “Overview”RAMP introduces the Universal Licensing Core: a structured, cross-domain-portable model for expressing commercial licensing terms on any digital resource. A resource carries zero or more LicenseTerm entries — each term is a complete, self-contained access arrangement. Having multiple terms for a single resource is the normal case, not the exception.
The model was designed to cover a wide range of content types and legal arrangements: news articles, stock photos, academic papers, music recordings, patent design files, datasets, and software. The same proto shapes appear at both ends of the pipeline:
- Ingestion (
ResourceEntry.terms) — publishers declare terms when pushing resources into an Exchange catalog viaCatalogService.PushResources. - Emission (
Offer.terms) — the Exchange surfaces those same terms to agents onDiscoverResources, unchanged. No translation or reformulation.
Why multiple terms per resource?
Section titled “Why multiple terms per resource?”A single resource often has different access arrangements for different use cases. Examples:
- A news article is free for academic RAG but costs $0.05 per access for commercial entities.
- A stock photo can be licensed for editorial use (free with attribution) or commercial use (paid, with a 500,000-impression cap).
- A patent design file can be licensed for viewing ($0) or for manufacturing (per-unit fee with self-reported metering).
One resource entry, multiple terms — each covering a complete, distinct access arrangement.
Term semantics
Section titled “Term semantics”Every LicenseTerm has a TermSemantics value:
Pricing is required on every term regardless of semantics — absent Pricing is a validation error, and model = FREE must be stated explicitly (absent Pricing is not free). An agent cannot act on a priceless term, so the machine-readable price is always present even when the rest of the terms are deferred to a document.
ENUMERATED — the machine fields (restrictions, quotas, obligations) are the complete, authoritative expression of the term. They must be internally consistent (a term may not contradict itself), are validated and normalized at ingest, and are surfaced on every offer. Restrictions are not an Exchange-side gate the requester must pass to see a term: discovery returns every scope-covered term and the agent self-selects the one whose restrictions it can honour, bearing compliance; enforcement happens downstream at usage reconciliation. An Exchange or Broker MAY, as a convenience, pre-filter offers using attributes the requester volunteers (function / geography / user-type), but that is advisory, not enforcement. So if a term declares ai-train prohibited, that prohibition rides on the offer and binds the transaction the agent accepts.
REFERENCE_ONLY — the document at License.uri (which must be present) is the authoritative, complete source for restrictions, quotas, and obligations, and the agent must fetch and read it before using the resource. The machine fields are optional in this mode — the publisher MAY send Pricing alone — but any restrictions/quotas/obligations they do include must be accurate: they MUST NOT contradict the referenced document, and whatever is expressed is enforced, exactly as under ENUMERATED. Because License.uri is always present for REFERENCE_ONLY, License.uri_digest (a method:hexdigest pin of the document) MUST be present so the agent can verify the fetched bytes match what was offered. The same requirement applies to any ENUMERATED term that carries a uri (mutable or not) — a pinned digest is what makes the referenced document tamper-evident. Pricing is still stated machine-readably. This mode is designed for complex license arrangements (music rights, patent portfolios, MCPS/PRS collective management agreements) whose terms cannot be fully enumerated in a machine-readable form.
Restrictions
Section titled “Restrictions”A Restriction constrains one licensing dimension:
| Kind | What it constrains | Vocabulary source |
|---|---|---|
FUNCTION | What the agent may do with the resource | (ramp.v1.vocab_enum) on RESTRICTION_KIND_FUNCTION |
GEOGRAPHY | Where the agent is operating | (ramp.v1.vocab_enum) on RESTRICTION_KIND_GEOGRAPHY |
USER_TYPE | What kind of entity the agent represents | (ramp.v1.vocab_enum) on RESTRICTION_KIND_USER_TYPE |
The token lists are authored as proto-native buf options on the RestrictionKind enum values (no side-car JSON registry); the functiontokens / geographytokens / usertypes constant packages and their IsRegistered checks are generated from them.
Each restriction carries:
permitted[]— tokens allowed on this axis. Empty = any value permitted.prohibited[]— tokens blocked on this axis. Takes precedence overpermitted[].advisory— whenfalse(the default), the restriction is binding: an agent that cannot evaluate every token in it (including an unknown vendor token) MUST decline the term. Setadvisory: trueto downgrade an unverifiable restriction to non-blocking. (Fail-closed by default — a forgotten flag fails safe.)
Reading a restriction: a value is in-scope when it matches at least one permitted[] token AND matches none of the prohibited[] tokens. Multiple restrictions on the same term are AND-combined — the agent must satisfy all of them. The agent applies this itself when self-selecting a term; the Exchange does not pre-filter terms against requester attributes.
Standard function tokens: ai-input, ai-train, ai-index, search, display, editorial, commercial, manufacture, sync.
Standard geography tokens: ISO 3166-1 alpha-2 codes (US, DE, GB, …) plus regional aliases EU, EEA, and the wildcard * (worldwide).
Standard user-type tokens: individual, academic, non_profit, news_publisher, broadcaster, commercial_entity.
Unknown tokens during ingest produce a PushResourcesResponse.warnings[] entry — the term is accepted but flagged. This is forward-compatible: new vocab tokens can be added to the registry and used immediately without breaking existing Exchange deployments.
Quotas
Section titled “Quotas”A Quota caps how much a licensee may consume before a term expires or must be renegotiated. Quotas gate term validity — they are not billing quantities. Billing is handled by Pricing.
Each quota has:
metric— the unit being capped (a registered token from the(ramp.v1.vocab)option onQuota.metric, or avendor:namespaced custom).limit— the maximum value in the given window.window—HOURLY,DAILY,MONTHLY, orTOTAL(lifetime cap, never resets).
Standard metric tokens: accesses, tokens, input-tokens, display-words, impressions, copies, seats, units-manufactured.
Example: a stock photo with an impressions cap of 500,000 lifetime uses:
quotas: [{ metric: "impressions", limit: 500000, window: TOTAL }]Obligations
Section titled “Obligations”An Obligation is a post-use behavioral requirement. Attribution and contribution are obligations, not pricing models — they belong here, not in PricingModel.
Each obligation has:
kind— what the agent must do (see table below).trigger— when the obligation activates.scope_license— the license derivatives must be released under, as aLicense(required forSHARE_ALIKE; setidfor an SPDX short-id and/oruri). A referencedurirequires auri_digest, the same swap-protection as any other license reference.detail— human-readable text (recommended for all kinds, e.g., exact attribution wording or notice text; anOTHERobligation without it produces a lint warning).
| Kind | Description |
|---|---|
ATTRIBUTION | Credit the author or publisher whenever the resource is used |
CONTRIBUTION | Good-faith payment — amount suggested, not contractually fixed |
SHARE_ALIKE | Derivatives must be released under the same license (CC-BY-SA / GPL style) |
NETWORK_COPYLEFT | Network service triggers copyleft (AGPL style) |
NOTICE | Include the specified copyright notice |
OTHER | Custom requirement, described in detail |
| Trigger | When it fires |
|---|---|
ON_USE | Any use of the resource |
ON_DISTRIBUTION | When copies are distributed |
ON_NETWORK_SERVICE | When served over a network |
ON_DERIVATIVE | When a derivative work is produced |
Key distinction from the retired pricing model values: attribution is not a payment model. A resource can require attribution and charge per-access. A resource can require contribution and be subscribed. Keeping them separate in ObligationKind allows any combination of pricing and behavioral requirements.
Revenue-share arrangements
Section titled “Revenue-share arrangements”RAMP has no revenue-share pricing model, and that is deliberate. PricingModel covers the three charging structures an Exchange can quote, sign, and compare at transaction time — FREE, PER_UNIT, FLAT — each with a concrete unit_cost. A revenue share has no transaction-time price: the rate and its reconciliation are an off-protocol agreement between the agent and the publisher. Encoding it as a pricing model would either be a bare label with no rate (the agent still has to ask “what share?”) or would pull the commercial terms of that agreement into the signed, cross-exchange-comparable Pricing — which the protocol never enforces and would make offers no longer price-comparable.
Instead, a revenue-share arrangement is expressed with primitives already in the core, exactly like a subscription:
- A
Pricing{model: FREE}term — there is no per-access charge. - Gated by an agreement scope, e.g.
scopes: ["revshare:publisher-x"]. The agent that has signed the deal holds a delegation JWT carrying the matching scope; everyone else never sees the term. - A
ReportingObligation(the offer-level reporting requirement) so usage is reported. Revenue is then settled off-protocol from those reports.
So “pay per crawl or enter the revenue-share deal” is just two LicenseTerms on the same resource: a public PER_UNIT term and a scope-gated FREE term. The agent self-selects. This is the same shape as the academic dataset subscription example below.
For CoMP interop, a CoMP revshare rate is carried verbatim in the ramp-comp-v1 ext (comp.license[].revshare) rather than mapped onto a pricing model — see CoMP extension. Parity by mapping, not by duplication.
Metering modes
Section titled “Metering modes”Pricing.metering (field 9, PricingMetering) controls how usage is tracked after a transaction:
| Mode | Description |
|---|---|
ONLINE (default) | The Exchange tracks usage events in real time. ReportUsage is required. |
NONE | One-time perpetual sale. The billing_id is issued at ExecuteTransaction and the ledger entry is closed immediately. No ReportUsage required. |
OFFLINE_SELF_REPORTED | Physical-world consumption (e.g. units manufactured from a licensed design file). The agent self-reports; the Exchange audits. |
NONE is appropriate for stock images with perpetual licenses, font licenses, one-time CAD file purchases, and any resource where the entire commercial relationship is settled at the time of the transaction.
OFFLINE_SELF_REPORTED is appropriate for IP licenses where consumption events happen outside the digital domain: a design file licensed for manufacturing, a recipe licensed for commercial production, a musical composition licensed for physical pressing.
Cross-domain examples
Section titled “Cross-domain examples”News article — two terms
Section titled “News article — two terms”A tech news publisher offers the same article under two arrangements:
Term 1 — free for academic RAG:
semantics: ENUMERATEDrestrictions: - kind: FUNCTION, permitted: ["ai-input"], prohibited: ["ai-train"] - kind: USER_TYPE, permitted: ["academic"]obligations: - kind: ATTRIBUTION, trigger: ON_USE, detail: "Cite TechCrunch at the original URL"pricing: { model: FREE }Term 2 — paid for commercial entities:
semantics: ENUMERATEDrestrictions: - kind: FUNCTION, permitted: ["ai-input", "ai-index"] - kind: USER_TYPE, permitted: ["commercial_entity"]pricing: { model: PER_UNIT, unit: "accesses", rate: 0.05, currency: "USD" }obligations: - kind: ATTRIBUTION, trigger: ON_USE, detail: "Cite TechCrunch at the original URL"An academic RAG agent matches Term 1. A commercial legal research platform matches Term 2. The Exchange surfaces both terms in Offer.terms; the agent picks the applicable one and transacts.
Stock photo — impressions quota + perpetual license
Section titled “Stock photo — impressions quota + perpetual license”A stock photo agency licenses a photo for commercial display:
semantics: ENUMERATEDrestrictions: - kind: FUNCTION, permitted: ["display"] - kind: GEOGRAPHY, permitted: ["*"]pricing: { model: FLAT, rate: 1.20, currency: "USD", metering: NONE }quotas: - { metric: "impressions", limit: 500000, window: TOTAL }obligations: - kind: ATTRIBUTION, trigger: ON_USE, detail: "© GettyImages. All rights reserved."metering: NONE means the buyer pays once and the ledger closes immediately — no ReportUsage required. The impressions quota is a contractual cap, not an online-enforced limit.
Patent design file — manufacture function + offline metering
Section titled “Patent design file — manufacture function + offline metering”A design licensing firm licenses a 3D-printable part:
semantics: ENUMERATEDrestrictions: - kind: FUNCTION, permitted: ["manufacture"] - kind: GEOGRAPHY, permitted: ["*"]pricing: { model: FLAT, rate: 200.00, currency: "USD", metering: OFFLINE_SELF_REPORTED }quotas: - { metric: "units-manufactured", limit: 1000, window: TOTAL }obligations: - kind: CONTRIBUTION, trigger: ON_USE, detail: "Suggested royalty: $0.50 per unit above 1,000"The $200 fee covers a license to manufacture up to 1,000 units. The agent self-reports manufacturing runs. The Exchange audits. Above 1,000 units, the agent is expected to negotiate a new term or pay the suggested contribution.
Licensed music track — complex rights
Section titled “Licensed music track — complex rights”A music rights holder for a sync license:
Term 1 — machine-enumerable sync rights:
semantics: ENUMERATEDrestrictions: - kind: FUNCTION, permitted: ["sync"] - kind: GEOGRAPHY, permitted: ["*"]pricing: { model: FLAT, rate: 500.00, currency: "USD", metering: NONE }obligations: - kind: NOTICE, trigger: ON_DISTRIBUTION, detail: "℗ 2024 Example Records. Licensed under MCPS license MR-7741."Term 2 — full MCPS/PRS terms by reference:
semantics: REFERENCE_ONLYlicense: uri: "https://www.mcps-prs-alliance.co.uk/license/MR-7741" name: "MCPS/PRS Blanket Sync License MR-7741" uri_digest: "sha256:3b1f8e0c…"pricing: { model: FLAT, rate: 500.00, currency: "USD" }Pricing is required even on a REFERENCE_ONLY term — the human-readable terms live in the referenced document, but the machine-readable price is always stated.
The Exchange surfaces both terms. A sophisticated agent checks the REFERENCE_ONLY term to verify the machine-enumerable Term 1 matches the authoritative document before committing.
Academic dataset — seat quota + share-alike
Section titled “Academic dataset — seat quota + share-alike”A data provider licenses a research dataset:
semantics: ENUMERATEDscopes: ["subscription:institution"]restrictions: - kind: FUNCTION, permitted: ["ai-train", "ai-input"] - kind: USER_TYPE, permitted: ["academic", "non_profit"]pricing: { model: FREE }quotas: - { metric: "seats", limit: 10, window: MONTHLY }obligations: - kind: SHARE_ALIKE, trigger: ON_DISTRIBUTION, scope_license: { id: "CC-BY-NC-SA-4.0" }, detail: "Trained models using this dataset must be released under CC-BY-NC-SA 4.0"The institutional subscription is settled off-protocol; access is gated on-protocol by the subscription:institution scope (the term is model: FREE because there is no per-access charge — the subscribing institution’s delegation JWT carries the matching scope). Up to 10 researchers in the subscribing institution can use the dataset. Any model trained on this dataset that is released publicly must carry the same license.
Vocabulary registry
Section titled “Vocabulary registry”The open vocabulary axes are proto-native — each registered token list is authored once, as buf custom options directly on the field or enum value that uses it (no side-car JSON registry):
- function / geography / user-type tokens —
(ramp.v1.vocab_enum)on theRESTRICTION_KIND_FUNCTION/RESTRICTION_KIND_GEOGRAPHY/RESTRICTION_KIND_USER_TYPEenum values - quota metrics —
(ramp.v1.vocab)onQuota.metric - pricing units —
(ramp.v1.vocab)onPricing.unit
The protoc-gen-rampvocab buf plugin reads these options structurally and generates a typed constant package per axis (functiontokens, geographytokens, usertypes, quotametrics, pricingunits) with an IsRegistered membership check; the constants, the membership check, and the validation all derive from the single authored list and cannot drift. Geography registers only the non-ISO specials (*, EU, EEA); ISO 3166-1 alpha-2 codes are conventional and checked at ingest. On the wire, Restriction.permitted/prohibited tokens carry only a structural bound (1–64 chars, no whitespace/control characters) — code-level membership is an ingest concern, consistent with the rest of the licensing invariants.
Unknown bare tokens at ingestion produce PushResourcesResponse.warnings[] entries — they do not cause rejection. This allows publishers to use new vocabulary tokens (or vendor: namespaced customs) before the registry is updated, at the cost of a non-enforced restriction on older Exchange deployments.