Skip to content

Proto: RAMP v1

Source: proto/ramp/v1/ramp.proto

The core protocol. Both AI agents and Brokers are valid clients.

RPCRequestResponseDescription
DiscoverResourcesResourceQueryResourceResponseDiscover available resource offers matching the query. Steps 2-3 in the RAMP flow.
ExecuteTransactionTransactionRequestTransactionResponseCommit to an offer and receive delivery information. Steps 4-5 in the RAMP flow.
ReportUsageUsageReportUsageReportResponseSubmit a post-usage report for a completed transaction. Step 7 in the RAMP flow.
DisputeTransactionDisputeRequestDisputeResponseSignal a resource dispute for a completed transaction. Filed by the agent when delivered resource does not match what was promised (hash mismatch, resource unavailable, wrong resource). The Exchange records the dispute and initiates resolution. Resolution mechanics (refund, credit, re-delivery) are implementation- specific — this RPC standardizes the dispute signal, not the outcome.
RequestDomainVerificationDomainVerificationRequestDomainVerificationChallengeRequest a domain verification challenge for provider onboarding. Used by ramp-cli to prove domain control before pushing signing keys. Follows the ACME HTTP-01 pattern (Let's Encrypt).
ConfirmDomainVerificationDomainVerificationConfirmationDomainVerificationResultConfirm domain verification and register a signing key. Called after the challenge token is placed at the provider's domain.
RegisterRegisterRequestRegisterResponseCreate the calling agent's account with the Exchange. The caller's identity is proven by the request signature — the Exchange derives who is registering from the verified signature, never from the request body. Registering again for the same agent returns the same billing_ref (idempotent by design), which is why this RPC carries no idempotency_key. A refused registration travels as a non-OK transport error carrying ErrorDetail.registration_failure.
GetAccountStatusGetAccountStatusRequestGetAccountStatusResponseRead-only check of whether the calling agent's account is active. Identity comes from the request signature, so the request carries no identifying field.

Optional RPC for providers/CMS/third-party intelligence providers to push content metadata.

RPCRequestResponseDescription
PushResourcesPushResourcesRequestPushResourcesResponsePush or update resource entries in the Exchange catalog.
RemoveResourcesRemoveResourcesRequestRemoveResourcesResponseRemove resource entries.
RefreshCatalogRefreshCatalogRequestRefreshCatalogResponseTrigger a full catalog refresh from configured sources.

The Broker entry point. Resolve(DiscoveryRequest) → DiscoveryResponse is discovery-only: a client sends the URIs/query it wants resolved and receives offer_groups (one OfferGroup per URI, each carrying the full signed Offer) or a typed absence_reason with empty offer_groups when nothing licensable was found. “No result” is a successful answer; malformed requests, auth failures, and internal faults are non-OK transport errors carrying an ErrorDetail. Resolve does not deliver inline — the per-transaction result (transaction id, billing id, retrieval endpoint, …) is returned on TransactionResponse via the separate execute path, routed by Offer.exchange.

RPCRequestResponseDescription
ResolveDiscoveryRequestDiscoveryResponseResolve runs the broker discovery flow for the requested URIs/query: it fans out to one or more Exchanges and returns the merged offers. It is pure discovery — it selects and returns offers, never executes a transaction, so it neither charges nor produces transaction denials. A denial is raised only when the agent later calls ExchangeService.ExecuteTransaction on a selected offer, and rides there on TransactionResponse.DenialReason. A result returns OK with offers populated on DiscoveryResponse.offer_groups (one OfferGroup per requested URI). A request that ran but yielded nothing licensable (not in catalog, no offers, entitlement/budget absence, upstream temporarily unavailable) returns OK with DiscoveryResponse.absence_reason set and empty offer_groups — "no result" is a successful answer, mirroring DiscoverResources (ADR-019 §2). Here "authz" means resource entitlement (→ OK + absence); transport authentication failures are a different axis and, like malformed requests and internal faults, are non-OK transport errors carrying an ErrorDetail.
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
requesterRequester3Requester identity — who is making this request, what scopes they have, and optional delegation chain.
urisrepeated string8Resource URIs being queried.
acceptable_restrictionsrepeated AcceptableRestriction9The limits this query operates within, per restriction axis (function, geography, user-type, …) — see AcceptableRestriction. Advisory selection inputs the Exchange/Broker MAY pre-select offers against (convenience, not enforcement); the agent self-selects and bears compliance.
deadlineoptional Duration6Maximum time the caller will wait for a response. Exchange SHOULD prioritize speed over completeness when tight. Absent = "0.5s" default (proto-JSON encodes Duration as seconds).
supported_profilesrepeated string7Domain extension profiles the caller understands. Declares which ext field vocabularies the caller can parse and act on. The Exchange SHOULD include profile-specific ext fields in Offers when the caller declares support. The Exchange MAY skip expensive metadata computation (e.g., retraction checking, consolidation verification) when the caller does not declare the relevant profile. Absence means "send all available metadata" — Exchange MUST NOT withhold ext fields solely because the caller omitted this field. Values match the Exchange's WellKnownManifest.supported_profiles entries. Examples: ["ramp-news-v1", "ramp-academic-v1", "ramp-legal-v1"]
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

The limits a query operates within on one restriction axis, in the same RestrictionKind vocabulary the terms use. The Exchange/Broker MAY pre-select offers whose term restrictions fall within these (convenience, not enforcement). Used in ResourceQuery and DiscoveryRequest.

FieldTypeNumberDescription
axisRestrictionKind1Which axis (same enum as Restriction.kind): FUNCTION / GEOGRAPHY / USER_TYPE / OTHER.
valuesrepeated string2The values the query operates within on this axis — same token vocabulary as the terms (e.g. FUNCTION ["ai-train"], GEOGRAPHY ["US", "EU"]).
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
exchangestring3Canonical domain of the responding Exchange.
offersrepeated Offer4Flat list of offers (for single-URI queries).
offer_groupsrepeated OfferGroup5Offers grouped by requested URI (for multi-URI batch queries). When populated, offers SHOULD be empty to avoid ambiguity.
rate_limitoptional RateLimitInfo6Rate limit status for this caller. Present when the Exchange enforces per-caller rate limits on discovery. Enables agents/Brokers to throttle proactively rather than hitting hard limits. Particularly important when a Broker fans out the same batch query to multiple Exchanges — mid-batch rate limiting can cause partial results if not signaled early.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.
FieldTypeNumberDescription
uristring1The URI this group of offers is for (echoed from ResourceQuery.uris).
offersrepeated Offer2Zero or more offers for this URI. Empty = resource not available.
discovery_methodoptional DiscoveryMethod3How this URI was discovered by the Broker (v2 extension point). v1: always DISCOVERY_METHOD_EXCHANGE (Broker queried an Exchange). v2: may include DISCOVERY_METHOD_SEARCH (URI found via search engine like Exa), DISCOVERY_METHOD_RECOMMENDATION, etc. The Broker discovers URIs through any source, then routes through Exchange for pricing/transaction. The discovery method does not affect the transaction flow — it's metadata for the agent to understand how the resource was found.
absence_reasonoptional OfferAbsenceReason4Why no offers are available for this URI. Present when offers is empty. Enables agents/Brokers to distinguish "resource not in catalog" from "resource blocked for your use case" without trial-and-error transactions. Analogous to OpenRTB nbr codes and Shutterstock per-item error metadata in batch responses.
restriction_filtersrepeated RestrictionKind5When absence_reason = RESTRICTION_FILTERED, the restriction axes that drove the convenience pre-filter, in the same RestrictionKind vocabulary the terms use (e.g. [GEOGRAPHY] when the requester's stated geography matched no term). Advisory diagnostics, not an enforcement verdict.

Rate limit status modeled after IETF RateLimit header fields.

FieldTypeNumberDescription
limitint321Maximum requests allowed in the current window.
remainingint322Requests remaining in the current window.
reset_atTimestamp3When the current window resets (UTC). After this time, remaining resets to limit.
windowoptional Duration4Duration of the rate limit window (e.g. 60s = per-minute limit).

Identity and entitlements only — who is asking and what they’re entitled to. What they’re asking for (uris) and the limits they’ll accept (acceptable_restrictions) live on the ask (ResourceQuery / DiscoveryRequest), not here. Used in ResourceQuery and DiscoveryRequest.

FieldTypeNumberDescription
idstring1Unique requester identifier (e.g., "agent-research-bot-001").
domainstring2Domain the requester belongs to — used for public key lookup. Keys published at {domain}/.well-known/ramp.json (WellKnownManifest, role=ROLE_AGENT).
typeRequesterType3What kind of entity is making this request.
nameoptional string4Human-readable name (e.g., "Acme Research Assistant").
scopesrepeated string6Entitlement scopes. Declare what the requester can access. The Exchange filters its catalog to resources matching these scopes. Resources outside the scopes are not returned — the requester never learns they exist. This is the enforcement mechanism for both enterprise RBAC and open-market subscription entitlements. Scope format: colon-separated segments, "{domain}:{permission}" or "{profile}:{permission}", optionally multi-segment ("dist:US:CA"); matching is segment-wise per the rule below (no implicit hierarchy). Examples: "credit:read" — can access credit reports "subscription:marketdata-2026" — has active MarketData subscription "academic:" — full access to academic resources "internal:reports" — can access internal reports "" — unrestricted (public Exchange default) Matching is SEGMENT-WISE (":" separated). A granted scope G covers a required scope R iff, segment by segment, each G segment equals the corresponding R segment or is ""; a terminal "" matches all remaining segments. There is NO implicit prefix match, and a grant NARROWER than the requirement does not cover it (G must be equal-to-or-broader than R). Examples: "dist:" covers "dist:US" and "dist:US:CA"; "dist:US:" covers "dist:US:CA" but not "dist:EU"; bare "dist" covers only "dist"; granted "dist:US:CA" does NOT cover required "dist:US"; "*" covers everything. This same rule governs LicenseTerm.scopes — one algorithm protocol-wide. When empty, Exchange applies its default access policy (typically returns all publicly available resources).
delegationoptional Delegation7Optional delegation — present when the requester acts on behalf of another entity (user, organization, upstream agent).
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Scoped, time-limited, spend-capped credential. The credential itself is opaque bytes carried in token, and token_format selects how to interpret them: "jwt" (the default and sole format; the field stays open for a future one). The format is never encoded as a prefix inside the token bytes. The token is a holder-bound JWT: a chain of cnf-linked JWTs (RFC 7800 cnf.jkt = RFC 7638 thumbprint) where each child is signed by the key its parent named and narrows scope, and the holder proves possession by signing the request (RFC 9421).

FieldTypeNumberDescription
principal_domainstring1Who granted this delegation (domain for public key lookup).
principal_idstring2Principal's identifier (e.g., "user@acme.com", "marketdata.example.com").
scopesrepeated string3Scopes granted by this delegation. MUST be a subset of the principal's own scopes (attenuation — can only narrow, not widen).
expires_atTimestamp4When this delegation expires. Exchange MUST reject expired tokens.
max_spend_centsoptional int645Maximum spend in currency minor units (e.g., cents for USD). Exchange tracks cumulative spend against this cap.
max_accessesoptional int329Maximum number of accesses allowed under this delegation. Exchange tracks cumulative access count against this cap. Deny with DENIAL_REASON_QUOTA_EXCEEDED when count >= limit. For subscriptions with "10,000 accesses/month", this carries the ceiling.
quota_periodoptional Duration10Quota reset period. How often the access/spend counters reset. Example: 30 days for monthly subscriptions — "2592000s" on the wire (proto-JSON encodes Duration as seconds; "720h" is not accepted). When absent, the quota is lifetime (bounded only by expires_at).
tokenbytes6Token bytes. A JWT (base64url-encoded JWS).
token_formatstring7Token format: "jwt" (default). Empty is treated as "jwt". The field stays open for a future format.
revocation_urioptional string8Optional: URI for real-time revocation checking. Exchange MAY check this for high-value transactions. Not checked for routine low-value access (performance tradeoff).
issueroptional string11Token issuer. OIDC issuer URL or GNAP grant server URL. Exchange uses this for JWT validation (OIDC discovery → JWKS) or GNAP token introspection.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Delegation claims. The claim vocabulary carried inside the token is not re-listed here — the authoritative registry is the Delegation-Claims Profile table in authentication.mdx. The one claim worth restating: every delegation MUST carry a holder binding (the cnf claim, cnf.jkt = the RFC 7638 thumbprint of the holder key) — the request-signing key MUST hash to cnf.jkt, or the token is rejected. Without it the token is bearer-usable. Everything else (scope, spend cap, expiry, etc.) is optional and defined in that single source of truth.

Narrowing example: An agent can further restrict (but never widen) a delegation by issuing a child JWT:

  • Original: scope: credit:*, max_spend_cents: 100000
  • Attenuated: scope: credit:read, max_spend_cents: 20000, uris: duns:123*

Multi-hop forwarding (no message — HTTP layer)

Section titled “Multi-hop forwarding (no message — HTTP layer)”

There is no in-message hop chain. Multi-hop forwarding (Agent → Broker → … → Exchange) is a stack of RFC 9421 HTTP Message Signatures: each forwarding party adds one labeled signature, and each signature covers the request plus the prior hop’s signature, so the ordered set of signatures is the chain (tamper-evident, order-bound). The Exchange resolves each keyid (an RFC 7638 thumbprint) in the signer’s WBA directory at {domain}/.well-known/http-message-signatures-directory, verifies every signature, and enforces RequestConstraints.max_hops / WellKnownManifest.max_intermediary_hops by counting them. Responses do not retrace the chain — the terminal Exchange returns directly to the originating agent (bound by agent_identity_hash).

FieldTypeNumberDescription
offer_idstring1Unique identifier for this offer, assigned by the Exchange.
titleoptional string2Resource title (human-readable, for display/logging).
pricingPricing3Pricing for this offer. An offer represents a single licensing arrangement: each projected LicenseTerm yields its own offer, so this is that term's pricing (the authoritative copy lives in terms[].pricing). Used for cross-exchange comparison and Broker ranking. A resource with multiple alternative terms (e.g. dual-licensed) produces multiple separate offers, one per term — never one offer with a "headline" picked among them.
delivery_methodDeliveryMethod4How resource will be delivered.
reportingoptional ReportingObligation5Post-usage reporting requirements for this offer.
expires_atoptional Timestamp6When this offer expires (ISO 8601).
identityoptional ResourceIdentity7Resource identity for cross-exchange deduplication. Enables Brokers to recognize the same resource offered by different Exchanges and compare pricing.
exchangestring8Canonical domain of the Exchange that issued this offer (e.g. "exchange.example.com"). This is the execute-routing target: the agent (or a relaying Broker) sends the ExecuteTransaction call for this offer to this Exchange. Because it is an ordinary Offer field it falls inside the signed bytes (see signature below — the signature covers every field except signature / signature_algorithm), so an intermediary cannot redirect the execute call to a different Exchange without invalidating the offer. This enables multi-Exchange fan-out routing from the offer itself, retiring the X-RAMP-Exchange-Endpoint transport header.
signaturestring9REQUIRED. JWS (alg=EdDSA) over the canonical serialization of the ENTIRE Offer — every field, including pricing, terms (the full licensing payload), expires_at, and exchange. Only signature and signature_algorithm are excluded from the signed bytes. expires_at is signed so the offer's validity window is integrity-protected: a relaying Broker cannot extend (or shorten) the TTL of a signed offer to replay it outside the window the Exchange intended. CANONICAL SIGNING (RFC 8785 JCS over canonical proto-JSON). The signed bytes are: signed_payload = JCS( protojson(msg with signature + signature_algorithm cleared) ) i.e. render the message to canonical proto-JSON with the PINNED option set below, then apply RFC 8785 (JSON Canonicalization Scheme). Deterministic protobuf BINARY marshaling is explicitly NOT canonical across languages and versions (protobuf's own caveat), so it cannot be a cross-language signing primitive; JCS over proto-JSON can be reproduced by ANY language (Go, TS, Python) without a protobuf binary codec, so a broker/exchange/client in any language signs and verifies byte-identically. This same definition applies to the agent offer-acceptance signature (AgentAcceptance.signature). PINNED proto-JSON option set (the arbiter is the Go-emitted golden vector — whatever these options render MUST be byte-identical across all languages): - enum values as NAME strings (not numbers); - int64 / uint64 / fixed64 as decimal STRINGS; - bytes as standard (padded) base64; - google.protobuf.Timestamp / Duration per the proto-JSON WKT rules (RFC 3339 string for Timestamp); - unpopulated fields are OMITTED (never emitted as defaults); - field naming is snake_case (the proto field name, UseProtoNames=true), the naming every SDK target shares — wire, corpus, and signed form are all snake_case; - google.protobuf.Struct (ext) → a plain JSON object; JCS then sorts its keys recursively, so the Struct case needs no special handling. UNKNOWN FIELDS. A canonicalizer either OMITS content it has no schema for or PRESERVES it, and the rule follows from which: - OMITTING (e.g. proto-JSON, which emits only schema-defined fields): such a canonicalizer CANNOT reproduce the signed bytes of a message carrying unknown fields — what it renders silently drops part of what the signer covered. It MUST refuse the message rather than emit the reduced bytes, and a verifier built on it MUST reject rather than verify over them. The refusal binds at EVERY depth: a nested message and each element of a repeated or map field carries its own unknown-field set. - PRESERVING (a canonicalizer that carries unrecognized members through): it reproduces the signed bytes faithfully, so there is nothing to refuse. Either way an APPENDED field cannot pass: an omitting canonicalizer refuses the message, and a preserving one renders the appended member into bytes the signer never covered, so the signature fails. Without the refusal the omitting case would fail OPEN — an intermediary could add unknown fields to an already-signed message and leave its signature verifying, smuggling unauthenticated content through a message the recipient treats as verified. Extensions therefore ride in ext / ext_critical, which are defined fields and inside the signed bytes — never as undeclared field numbers. Because the signature covers terms, pricing, expires_at, and exchange, an intermediary (Broker) cannot tamper with price, restrictions, quotas, obligations, the expiry, the execute-routing target, or any licensing term without invalidating it. Agent SHOULD verify the signature (RFC 2119) against the Exchange's public key, and MUST reject an offer whose expires_at is in the past.
signature_algorithmstring10JWS algorithm. Always 'EdDSA' for Ed25519 via JWS Compact Serialization.
subscription_idoptional string11If set, this offer is available under an existing subscription/deal. No per-request billing — usage tracked against subscription quota. Pricing.rate = "0" for subscription offers (zero marginal cost). The Broker SHOULD prefer subscription offers when available.
iab_categoriesrepeated string13IAB Content Taxonomy category codes. Enables agents to filter offers by topic (e.g., "only finance resources"). Uses IAB Content Taxonomy 3.1 codes.
attestationsrepeated ResourceAttestation14Signed attestations about the resource at this URI. Attestations provide cryptographic proof of resource properties from trusted parties (providers or verification vendors). Three verification levels determine what is independently verifiable: Level 0 (no attestations): Resource may carry identifiers (DOI, IPTC GUID) for identification, but nothing is cryptographically verifiable. Only CDN delivery failure is auto-disputable. Level 1 (self-attested): Provider signs own claims with Ed25519 key. Agent can independently verify content hash and token count. CDN delivery failure + content hash mismatch are auto-disputable. Level 2 (third-party attested): Independent verification vendor crawled the resource and attested to its properties. Agent trusts the attestation (does not re-verify hash). Token count discrepancy is auto-disputable when corroborated by CDN response size. Multiple attestations may be present (e.g., provider self-attestation plus a third-party verification). Agents choose which to trust.
data_as_ofoptional Timestamp16When the offered data was current. For dynamic resources (resource_mutability = DYNAMIC), this is the snapshot timestamp. Enables the Broker to evaluate freshness: "this credit report reflects data as of March 18" or "this drug database was updated today." Not set for STATIC resources (content doesn't change) or LIVE resources (content doesn't exist yet). The Broker compares this against RequestConstraints.max_data_age to filter stale offers. Example: agent requests max_data_age = 7 days, Broker drops offers where now() - data_as_of > 7 days.
subscription_quotarepeated SubscriptionQuotaInfo17Subscription quota state, when this offer is under a subscription. Enables the agent to see remaining quota before committing. Multiple entries when the subscription has independent quotas (e.g., access count + spend cap).
previewsrepeated Preview18Lightweight previews for offer evaluation. The Exchange holds URLs (50–200 bytes each); the provider's CDN serves the actual bytes. Agents fetch previews only when evaluating offers — not on every discovery query. Multiple previews at different sizes allow agents to pick the cheapest fetch for their evaluation needs. Per content type: Image: watermarked thumbnail (150–450px JPEG) Video: short clip (10–30s MP4, watermarked) Audio: short clip (15–30s MP3, low-bitrate or watermarked) Text: snippet or abstract (first 200 words as text/plain) Data: sample records (1–3 rows as application/json) Stream: optional frame capture or none (streams are priced by time) Modeled after Shutterstock (multi-size thumbnail URLs), Spotify (preview_url to 30s clip), IIIF (parameterized image URLs), and OpenRTB native (img.url + dimensions).
termsrepeated LicenseTerm19Licensing terms for this offer, sourced from the publisher's ResourceEntry. Multiple terms when the resource has different arrangements by use case. See: Universal Licensing Core section.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Signed envelope of claims from a trusted party (provider or verification vendor) about content at a specific URI.

FieldTypeNumberDescription
verifierstring1Canonical domain of the attesting party (e.g., "nytimes.com" for self-attestation, "doubleverify.com" for third-party attestation). Used to look up the verifier's attestation-signing keys in its WBA directory (WBAFile.keys) at https://{verifier}/.well-known/http-message-signatures-directory
keyidstring2RFC 7638 JWK Thumbprint (the RFC 9421 keyid) of the verifier's attestation-signing key, resolved against the verifier's WBA directory (WBAFile.keys). Identifies which Ed25519 key signed this attestation. Enables key rotation: new keys are published with overlapping validity, new attestations use the new key's thumbprint, old attestations remain verifiable while the old key is still published.
attested_atTimestamp3When this attestation was created. Agents use this to assess freshness (e.g., "I accept attestations up to N hours old for breaking news").
uristring4The resource URI this attestation covers. Must match the URI in the Offer or ResourceEntry this attestation is attached to.
claimsStruct5Signed claims about the resource (max 4KB). A JSON object containing whatever properties the attesting party can determine about the resource. Recommended claim names for interoperability: estimated_quantity (integer): estimated consumption quantity (e.g., token count for text) word_count (integer): word count (estimated_quantity ~ word_count * 1.32 for text) language (string): ISO 639-1 language code iab_categories (string[]): IAB Content Taxonomy 3.1 codes content_hash (string): hash of content in "method:hexdigest" format hash_method (string): algorithm used for content_hash Vendors MAY add vendor-specific claims (e.g., brand_safety, sentiment). The protocol does NOT define "quality score" — it is inherently subjective. If a vendor provides a proprietary score, the vendor defines what it means via their WellKnownManifest ext["ramp.attestation.claims_schema"].
signaturestring6Ed25519 signature over JCS-canonicalized (RFC 8785) representation of {verifier, keyid, attested_at, uri, claims}. JCS (JSON Canonicalization Scheme) produces deterministic UTF-8 bytes: lexicographic key sorting, ECMAScript number serialization, strict string escaping, no whitespace. Each attestation is self-contained — new claim fields do not invalidate old attestations because the signature covers the specific claims instance.

Three verification levels:

LevelConditionWhat’s Verifiable
0 — Noneattestations emptyCDN delivery failure only
1 — Self-attestedverifier matches provider domainContent hash + token count
2 — Third-partyverifier is a verification vendorToken count (with CDN corroboration)
FieldTypeNumberDescription
modelPricingModel1Provider's pricing model.
ratestring2Price in the provider's model, as an exact decimal string — e.g. "0.05" = $0.05 per article. NOT a float: money is decimal to avoid binary rounding and to allow arbitrary sub-cent precision (e.g. "0.0001234"). Denominated in currency.
currencystring3ISO 4217 currency code (e.g. "USD", "EUR").
unit_costoptional string4Normalized cost per unit — the universal comparison metric, exact decimal string. For text: cost per token. For video: cost per second. For data: cost per record. For APIs: cost per call. Denominated in the Exchange's base_currency (from its WellKnownManifest).
estimated_quantityoptional int325Estimated quantity in the metering unit. For text: token count. For video: duration in seconds. For documents: page count. For data: record count.
license_duration_monthsoptional int327License duration in months. How long the granted access remains valid.
unitoptional string8Metering basis — the "per what" of PER_UNIT pricing. REQUIRED when model = PER_UNIT. Custom units namespace as "vendor:unit". Ignored for FREE / FLAT. The (ramp.v1.vocab) entries below are the SOLE authored source of the registered bare tokens. A buf plugin reads them structurally and emits the pricingunits constants + IsRegistered; ingest enforces membership from those. The CEL is STRUCTURE ONLY (empty / bare-form / vendor:namespaced) — it never lists the tokens, so it cannot drift from the registry.
meteringoptional PricingMetering9How usage is tracked for billing reconciliation. Absent = PRICING_METERING_ONLINE (default real-time tracking). NONE = one-time perpetual sale; no ReportUsage required after ExecuteTransaction. OFFLINE_SELF_REPORTED = agent self-reports physical-world consumption.

Pricing has no ext / ext_critical fields — the licensing core is closed.

Layered content identification for cross-exchange dedup and integrity verification.

FieldTypeNumberDescription
canonical_urloptional string1Provider's authoritative URL for this resource (rel="canonical"). Always available. Different per provider for syndicated content.
doioptional string2Digital Object Identifier — persistent, never changes.
iptc_guidoptional string3IPTC NewsML-G2 globally unique identifier. Present when resource flows through news wire syndication (AP, Reuters).
isnioptional string4International Standard Name Identifier for the creator.
content_hashoptional string5Hash of the content. Interpretation depends on hash_method: "simhash-v1" → locality-sensitive hash, for fuzzy dedup (Level 1) "sha256" → exact-match integrity hash (Level 2) Level 1 (SimHash): computed by Exchange from extracted text. Agent verifies that fetched content is "substantially similar." Tolerates dynamic page elements. Level 2 (SHA-256): computed by provider from deterministic payload. Agent verifies exact match. Requires provider to serve consistent content (e.g., API endpoint, static HTML, structured JSON). Mismatch = dispute. Commands premium pricing.
hash_methodoptional string6Hash algorithm and verification level. Examples: "simhash-v1", "minhash-v1", "sha256", "sha384"
resource_mutabilityResourceMutability8Signals whether this resource's content is stable, changes over time, or does not exist at offer time (live streaming). Drives hash verification behavior: STATIC: content_hash is stable. Agent SHOULD verify delivered content matches. DYNAMIC: content changes between offer and fetch (credit reports, drug databases). content_hash reflects state at offer generation time. Hash mismatch is expected and MUST NOT trigger automatic dispute. LIVE: content does not exist at offer time (streaming feeds, live broadcasts). content_hash is not applicable. The "resource" is the stream endpoint. Validated across 18 use cases: static content (articles, patents, legislation), dynamic data (credit reports, drug interactions, stock snapshots), and live streams (MarketData quotes, NPR broadcast, news monitoring feeds).
c2pa_manifestoptional string7C2PA content credentials manifest URI. Points to a sidecar or embedded C2PA manifest for this resource. C2PA-aware agents MAY follow this URI to validate the full provenance chain (creator identity, transformation history, ingredient composition) using C2PA libraries (JUMBF/COSE Sign1). C2PA-unaware agents can rely on c2pa_status and c2pa-bridged attestation claims instead. Formats: Sidecar: HTTPS URI to a .c2pa manifest file Embedded: same URI as canonical_url (manifest is inside the asset) Content Credentials Cloud: https://contentcredentials.org/verify?uri=...
c2pa_statusoptional C2PAStatus9Summary validation status of the C2PA manifest. Populated by the Exchange or a verification vendor after validating the C2PA manifest. Enables agents to filter for provenance-verified content without parsing JUMBF/COSE themselves. The full C2PA validation details (signer identity, trust list, action history, training/mining status) are carried in a ResourceAttestation with c2pa.* claims — see ramp-c2pa-v1 profile.
soft_bindingoptional string10Soft binding hash — content-derived identifier that survives format transcoding (resolution changes, compression, PDF-to-text extraction). Extracted from C2PA soft binding assertion when present. Enables post-delivery verification when the hard binding hash breaks due to legitimate format conversion. Algorithm specified in soft_binding_method. Values are algorithm-specific (e.g., perceptual hash hex string, watermark identifier).
soft_binding_methodoptional string11Algorithm used for soft_binding. Examples: "phash-v1" (perceptual hash), "c2pa-watermark" (C2PA invisible watermark), "chromaprint" (audio fingerprint).
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Quota status for a subscription within the current billing period. Appears on Offer (field 17) as a pre-commit snapshot and on TransactionResponse (field 17) as the post-transaction remaining quota. The field is repeated to support multi-dimensional quotas (e.g. access count + spend cap).

FieldTypeNumberDescription
subscription_idstring1Subscription this quota applies to.
quota_limitint322Total allowed in the current period.
quota_usedint323Used so far in the current period.
quota_remainingint324Remaining in the current period.
resets_atoptional Timestamp5When the quota counter resets (UTC).
unitoptional string6What is being metered. Distinguishes access count quotas from spend quotas from burst limits. Standard values: "accesses", "tokens", "spend_cents", "burst"

Lightweight resource preview for offer evaluation. The Exchange populates preview URLs during catalog ingestion; assets are served by the provider’s CDN, not by the Exchange. Carried on Offer (field 18, repeated).

FieldTypeNumberDescription
urlstring1URL to a preview asset (thumbnail, clip, snippet, sample). Served by the provider's CDN, not by the Exchange.
media_typestring2MIME type of the preview. Examples: "image/jpeg", "image/webp", "audio/mpeg", "video/mp4", "text/plain", "application/json"
widthoptional int323Dimensions in pixels (for images and video).
heightoptional int324Height in pixels (images and video)
durationoptional int325Duration in seconds (for audio and video clips).
sizeoptional string6Size category hint. Agents use this to select the right preview without fetching all of them. Standard values: "thumbnail" — smallest useful preview (100–150px or 5–10s) "preview" — mid-size for evaluation (300–500px or 15–30s) "sample" — larger / more detailed (for data: 1–3 sample records)
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
idempotency_keystring2Idempotency key (REQUIRED). The server MUST dedupe on this: a replay returns the original result rather than re-executing. The transaction's durable identity is the Exchange-assigned transaction_id in the response. Uniqueness is scoped to the verified RFC 9421 signer: the server dedupes per (authenticated caller, key), never globally, so a key chosen by one caller cannot collide with another's cached result.
requesterRequester4Requester identity — forwarded for authorization and audit.
itemsrepeated TransactionItem7The offers committed in this request (REQUIRED, min 1), each carrying its own reflected signed Offer + detached acceptance. A single offer is the degenerate 1-element list. The Exchange verifies each item's offer.signature (which covers pricing, terms, and expires_at) over the presented bytes against its own key — stateless, self-contained bearer tokens, with no reconstruct-from-catalog.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
agent_identity_hashstring10Identity that a delivered retrieval_endpoint is bound to: the RFC 7638 JWK Thumbprint of the agent's Ed25519 request-signing key (see "Retrieval-URL identity binding" above). Shared across the request; set once.
itemsrepeated TransactionResultItem13Per-offer results (one entry per committed item, in original order).
total_costoptional Cost14Aggregate cost across all items.
subscription_quotarepeated SubscriptionQuotaInfo17Post-transaction quota state. Tells the agent how much quota remains after this transaction. Enables proactive throttling ("1 access left"). Multiple entries for multi-dimensional quotas.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

A single offer commitment within a batch transaction.

FieldTypeNumberDescription
offerOffer3The FULL signed Offer for this batch entry, reflected back exactly as received at discovery. The Exchange verifies offer.signature over these presented bytes — stateless, no reconstruct-from-catalog. REQUIRED: every batch item carries its offer.
agent_acceptanceoptional AgentAcceptance4The agent's detached acceptance signature over this item's offer. Optional on the wire; the Exchange enforces presence per item at the service layer for relayed batches. Signed bytes = the canonical AgentAcceptancePayload form, with requester_* and idempotency_key taken from the ENCLOSING TransactionRequest and offer_sig = offer.signature.

The agent’s detached acceptance signature over an accepted Offer. It travels in the execute body alongside the reflected Offer and is independent of the transport (RFC 9421) request signature, so it survives any number of broker relays. The Exchange verifies it and binds the delivery URL to the agent’s key (RFC 7638 thumbprint). signature is a hex-encoded detached Ed25519 signature over the JCS-canonicalized (RFC 8785) proto-JSON of AgentAcceptancePayload — the same canonical signing form Offer.signature defines, reduced here to JCS(protojson(payload)) because the payload carries no signature fields to clear; signature_algorithm is EdDSA.

FieldTypeNumberDescription
signaturestring1Hex-encoded detached Ed25519 signature over the canonical AgentAcceptancePayload bytes (see the canonical-signing definition on Offer.signature).
signature_algorithmstring2Signature algorithm; "EdDSA" for Ed25519.

The canonical signing structure for AgentAcceptance. It is never sent on the wire — this message fixes the field set, and the byte layout is the canonical signing form defined on Offer.signature: RFC 8785 JCS over canonical proto-JSON with a pinned option set. Both halves are normative, so signer and verifier derive byte-identical signed bytes in any language without a protobuf binary codec, and the contract cannot drift between implementations. offer_sig is the accepted Offer.signature (which transitively binds pricing, terms, and expiry); requester_id, requester_domain, and idempotency_key come from the enclosing TransactionRequest.

FieldTypeNumberDescription
offer_sigstring1The accepted Offer's signature (Offer.signature). Anchors the whole signed offer without re-serializing its terms/pricing/expiry.
requester_idstring2Requester identity (Requester.id) the acceptance is bound to.
requester_domainstring3Requester domain (Requester.domain) the acceptance is bound to.
idempotency_keystring4The transaction's idempotency key — binds the acceptance to a single execute so it cannot be replayed under a different transaction.

Result for a single offer in a batch transaction.

FieldTypeNumberDescription
offer_idstring1The offer_id this result is for.
transaction_idstring2Exchange-assigned transaction identifier.
billing_idstring3Billing record identifier minted by the Exchange's billing adapter for this transaction (not the account handle — see RegisterResponse.billing_ref).
resource_titleoptional string4Resource title echoed from the Offer.
costCost5Cost for this item.
subscription_idoptional string6If under subscription, no per-request charge.
subscription_unit_valueoptional Cost11Computed per-unit cost for financial attribution on subscription transactions. Even when cost.amount="0" (subscription), this field carries the value of the access for accounting purposes (e.g., ASC 606 prepaid drawdown).
denial_reasonoptional DenialReason7Set if this specific item was denied (others may succeed).
restriction_mismatchesrepeated RestrictionKind13When denial_reason = RESTRICTION_NOT_SATISFIED, the restriction axes the request failed, in the same RestrictionKind vocabulary the terms use.
expires_atoptional Timestamp8When retrieval_endpoint expires.
retrieval_endpointoptional string12Signed retrieval URL for this item. Bound to the requesting agent's identity via the parent TransactionResponse.agent_identity_hash (shared across all batch items); expires at expires_at. Absent if this item was denied or its delivery_method is not signed-URL-based.
delivery_methodDeliveryMethod9How resource is delivered for this item.
reporting_obligationoptional ReportingObligation10Reporting requirements for this item.

Actual transaction cost.

FieldTypeNumberDescription
amountstring1Exact decimal string (not a float), e.g. "19.99". Denominated in currency.
currencystring2ISO 4217
unit_costoptional string3Effective cost per unit (decimal string)
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
idempotency_keystring2Idempotency key (REQUIRED). The server MUST dedupe on this so a replayed report does not double-count usage. The report's durable identity is the Exchange-assigned report_id in UsageReportResponse. Uniqueness is scoped to the verified RFC 9421 signer: the server dedupes per (authenticated caller, key), never globally, so a key chosen by one caller cannot collide with another's cached result.
transaction_idstring3Transaction ID from the delivery.
billing_idstring4Billing record identifier from the delivery (TransactionResultItem.billing_id).
usageUsage5How the resource was actually used.
timestampTimestamp6When the resource was used (ISO 8601).
exchangeoptional string8Exchange this report is for.
assetsrepeated UsageAsset9Assets that were delivered and used.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Requirements attached to a delivery.

FieldTypeNumberDescription
requiredbool1Whether post-usage reporting is required.
windowoptional Duration2Duration within which the report must be submitted (e.g. "86400s" = 24 hours; proto-JSON encodes Duration as seconds).
endpointoptional string3URL to submit the usage report to (if different from Exchange).
required_fieldsrepeated string4Field names that must be present in the report.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.
FieldTypeNumberDescription
functionrepeated string1How the resource was used. Standard values: "ai-train", "ai-input", "ai-index", "search", "display". Multiple allowed. CoMP-specific values available via ramp-comp-v1 extension profile.
subfnrepeated string2Sub-function detail. Standard values: "training", "rag", "grounding", "agent_view", "agent_actions".
consumed_quantityint323REQUIRED. Actual quantity consumed, in the metering unit from the Offer's Pricing. For text: tokens consumed. For video: seconds watched. For data: records accessed. Exchange cross-references against Offer.pricing.estimated_quantity.
displayed_to_useroptional bool4Whether resource/output was displayed to a human.
citation_includedoptional bool5Whether citation was included as required by the offer terms.
attributionrepeated AttributionDetail6Structured attribution details for each citation provided.
consumed_unitoptional string8Metering unit for consumed_quantity. Must match the Offer's Pricing.unit. If omitted, defaults to "tokens". Same token format as Pricing.unit: a bare registered token or a vendor:namespaced token.

Structured attribution metadata for usage reporting.

FieldTypeNumberDescription
displayed_urloptional string1URL displayed to the user as the attribution link.
formatoptional CitationFormat2How the citation was presented.
visible_to_useroptional bool3Whether the attribution was visible to the end user.

A single asset included in the usage report.

FieldTypeNumberDescription
uristring1Asset URI
titleoptional string2Asset title
package_idoptional string3Package identifier

Acknowledgment of a usage report. A successful response means the report was accepted; a rejection travels as a non-OK transport error carrying ErrorDetail.usage_report_rejection.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
report_idstring3Exchange-assigned report identifier. Required for the dispute chain — the agent must reference this report_id in DisputeRequest to prove that a usage report was filed before disputing. The complete evidence chain: Offer → Transaction (transaction_id, billing_id) → UsageReport → UsageReportResponse (report_id) → DisputeRequest (transaction_id + report_id)
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Agent signals a content delivery problem for a completed transaction.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
idempotency_keystring2Idempotency key (REQUIRED). The server MUST dedupe on this so a replayed filing does not open a duplicate case. The dispute's durable identity is the Exchange-assigned dispute_id in DisputeResponse. Uniqueness is scoped to the verified RFC 9421 signer: the server dedupes per (authenticated caller, key), never globally, so a key chosen by one caller cannot collide with another's cached result.
transaction_idstring3Transaction being disputed.
billing_idstring4Billing record identifier from the disputed transaction (TransactionResultItem.billing_id).
reasonDisputeReason5Reason for the dispute.
descriptionoptional string6Human-readable description of the issue.
received_content_hashoptional string7Evidence: content hash of what was actually received. Exchange compares against the hash promised in ResourceIdentity.
received_hash_methodoptional string8Hash algorithm the agent used
report_idstring9Must reference a filed UsageReport. The agent MUST file a UsageReport (via ReportUsage RPC) and receive a report_id BEFORE filing a dispute. This prevents fire-and-forget disputes and ensures the Exchange has the complete evidence chain: what was offered, what was transacted, what the agent reported using, and what the agent disputes. The dispute chain: Transaction → UsageReport → Dispute.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Exchange acknowledges and processes the dispute. A successful response means the dispute was accepted for processing; a refusal to file travels as a non-OK transport error carrying ErrorDetail.dispute_failure.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
dispute_idoptional string2Exchange-assigned dispute case identifier.
estimated_resolutionoptional Duration4Expected resolution timeline.
statusDisputeStatus5Current lifecycle status of the dispute. Tracks progression through the three-tier resolution process: Tier 1 (automated, <1s): FILED → AUTO_RESOLVED or EVIDENCE_NEEDED Tier 2 (rule-based, <24h): UNDER_REVIEW → RESOLVED Tier 3 (pattern investigation, async): ESCALATED → SETTLED → FINAL Losing party may appeal: RESOLVED → APPEALED → back to UNDER_REVIEW.
resolutionoptional ResolutionType6Resolution outcome, populated when the dispute reaches a terminal state (RESOLVED, SETTLED, or FINAL). Absent while dispute is in progress (FILED, UNDER_REVIEW, ESCALATED, etc.).
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Request an ACME-style domain verification challenge.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
domainstring2The provider domain to verify (e.g., "techcrunch.com").
caller_idoptional string3Caller identity (registered with the Exchange).
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Exchange returns a challenge token to be placed at the provider’s domain.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
tokenstring2Opaque challenge token. Provider must serve this at: https://{domain}/.well-known/ramp-verify/{token}
expires_atTimestamp3When this challenge expires. Provider must confirm before this time.
verification_urlstring4The exact URL the Exchange will fetch to verify.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Confirm domain verification and register a signing key.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
domainstring2The domain being verified.
tokenstring3The challenge token (echoed from DomainVerificationChallenge).
signing_keyoptional string4Optional: signing key to register upon successful verification. If present, the key is registered atomically with verification. Key format depends on CDN type (PEM for CloudFront, hex for HMAC).
cdn_typeoptional string5CDN type this key is for.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

A successful response means verification succeeded; a failure travels as a non-OK transport error carrying ErrorDetail.domain_verification_failure.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
key_idoptional string2If signing_key was provided: confirmation of key registration.
valid_untiloptional Timestamp4Verification is valid until this time. Provider must re-verify periodically.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Agent asks the Exchange to create its account. The caller’s identity is proven by the verified request signature, never asserted in the body; the operator-defined business payload rides in registration_data. Whether the Exchange inspects that payload follows its manifest: one publishing WellKnownManifest.registration_schema validates against that schema and refuses a non-conforming payload, one publishing none passes it through to its system of record uninspected.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
registration_dataStruct2Operator-defined registration payload; the business fields are not fixed in the wire contract. Whether the Exchange inspects it follows its manifest — see WellKnownManifest.registration_schema. The caller's identity is taken from the verified request signature, never from this payload.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Exchange returns the minted billing_ref — the opaque, long-lived, per-Exchange account handle — and the account’s current active state. A repeat Register for the same agent returns the same billing_ref; a refused registration travels as a non-OK transport error carrying ErrorDetail.registration_failure.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
billing_refstring2Opaque, long-lived, per-Exchange account handle minted by the Exchange. Means nothing on its own and is never accepted as caller input. A repeat Register for the same agent returns the same value.
activebool3Whether the account is currently active. Accounts may start inactive and be activated out-of-band by the Exchange operator.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Read-only check of whether the calling agent’s account is active. Deliberately carries no identifying field — the Exchange resolves the account from the verified request signature.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

The account’s current state. billing_ref is empty when the calling agent has no account yet.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
billing_refstring2The account handle minted at registration (see RegisterResponse.billing_ref). Empty when the calling agent has no account yet.
activebool3Whether the account is currently active.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Served at /.well-known/ramp.json by every RAMP participant (agent, exchange, broker, publisher). Single canonical document, role-tagged via role. Signing keys are not carried here — each participant publishes them in its WBA directory (the JWK Set at /.well-known/http-message-signatures-directory, modeled by WBAFile). Per-role fields are populated only when that role applies; consumers MUST ignore non-applicable fields based on role.

FieldTypeNumberDescription
verstring1RAMP protocol version of THIS MANIFEST DOCUMENT's schema — a namespace separate from the RPC envelope ver, deliberately not coupled to it. MUST equal "1.0"; consumers REJECT unrecognised major versions.
roleRole2Role this manifest describes.
domainstring3Canonical domain serving this manifest.
contactoptional string4Contact email (licensing, integration, security).
exchangesrepeated AuthorizedExchange7Publisher-only. Authorized exchanges for this publisher's resources. Like ads.txt — declares who may sell. MUST be empty for non-publisher roles.
catalog_contributorsrepeated CatalogContributor8Publisher-only. Authorized third-party catalog contributors. MUST be empty for non-publisher roles.
nameoptional string9Exchange-only. Human-readable Exchange name.
operatoroptional string10Exchange-only. Organization operating this Exchange.
operator_domainoptional string11Exchange-only. Operator's corporate domain (may differ from domain).
endpointoptional string12Exchange-only. ExchangeService endpoint URL. MUST be on the same host AND PORT that serve this manifest, or on a subdomain of that host on that port, and MUST NOT carry userinfo. A consumer refuses an endpoint anywhere else: this document is only as trustworthy as the host that served it, so an endpoint naming an unrelated host would let whoever answers for the manifest redirect a signed call to a party the signature never covered, and another port is another service the publisher of the manifest need not control. The host match is on a full dot-delimited label boundary, so evil-a.com is not a subdomain of a.com. A port equal to the scheme's default and an omitted port are the SAME port, so https://x, https://x:443 and x all match. An Exchange reachable on a non-default port names that port on both sides. (One paragraph deliberately: a blank line here routes the first paragraph into the generated types' JSON-Schema title, which the Pydantic/Zod export drops.)
health_endpointoptional string13Exchange-only. Health check endpoint URL.
catalog_endpointoptional string14Exchange-only. CatalogService endpoint URL (if exposed).
protocol_versions_supportedrepeated string16Exchange-only. Supported RAMP protocol versions (e.g. ["1.0"]).
pricing_models_supportedrepeated PricingModel17Exchange-only. Supported pricing models.
delivery_methods_supportedrepeated DeliveryMethod18Exchange-only. Supported delivery methods.
hash_methods_supportedrepeated string19Exchange-only. Accepted resource hash methods for attestation verification.
accepted_verifiersrepeated string20Exchange-only. Trusted attestation verification vendors (domains).
terms_urioptional string21Exchange-only. Terms of service URL.
privacy_urioptional string22Exchange-only. Privacy policy URL.
supported_profilesrepeated string23Exchange-only. Domain extension profiles this Exchange conforms to. See standards-layering docs.
supported_auth_methodsrepeated AuthMethod24Exchange-only. Authorization methods this Exchange supports (ordered by preference).
oidc_issueroptional string25Exchange-only. OIDC Discovery URL when OAuth methods are supported.
gnap_grant_endpointoptional string26Exchange-only. GNAP grant endpoint when GNAP is supported.
base_currencyoptional string27Exchange-only. Base currency for pricing (ISO 4217). All unit_cost values from this Exchange are denominated in this currency.
max_intermediary_hopsoptional int3228Exchange-only. Maximum forwarding hops this Exchange tolerates on an inbound request (Agent → Broker → … → Exchange), counted as RFC 9421 HTTP Message Signatures. A request carrying more SHOULD be rejected. Lets Exchanges publish their chain-depth tolerance so Brokers prune before forwarding. Absent = no published limit (Exchange applies its own default policy).
registration_schemaStruct29Exchange-only. JSON Schema (draft 2020-12) describing the RegisterRequest.registration_data object this Exchange expects. This field is the single home of the enforce/pass-through contract, and publishing it IS the enforcement switch. Present: this Exchange validates registration_data against the schema and refuses a non-conforming payload with REGISTRATION_FAILURE_REASON_INVALID_REGISTRATION_DATA, naming the offending members in RegistrationFailure.field_errors. Absent: registration_data is passed through to the system of record uninspected, so an Exchange that publishes no schema needs no change to stay conformant. Safety rules, because a consumer reads this schema out of a third party's manifest: it MUST be self-contained, and a consumer MUST NOT resolve a remote $ref out of it — doing so turns every reader into an SSRF vector aimed at a URL the schema's author chose. A consumer SHOULD bound validation time and recursion depth; draft 2020-12 pattern admits regexes with catastrophic backtracking. Size is capped at 16KB, measured as the UTF-8 bytes of this member as served in ramp.json; a consumer SHOULD reject an oversized schema and skip its local pre-check rather than truncate it, which leaves the Exchange's own enforcement the deciding check exactly as when no schema is published.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown values reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → ignore-unknown.

The pure WBA directory, served at /.well-known/http-message-signatures-directory (Content-Type: application/jwk-set+json). Holds each participant’s inline signing keys and an optional emergency-revocation pointer. Keys are identified by their RFC 7638 thumbprint (the RFC 9421 keyid).

FieldTypeNumberDescription
keysrepeated JsonWebKey1Signature-verification keys; ≥1 valid at serve time
revocation_urloptional string2Emergency key-revocation list URL (KeyRevocationList)

Inline RFC 7517 JWK. RAMP v1.0 supports Ed25519 only. Time bounds are RFC3339 strings; the validity window is half-open [not_before, not_after). Keys carry no kid label — a key is identified by its RFC 7638 thumbprint (the RFC 9421 keyid).

FieldTypeNumberDescription
ktystring2Key type. RAMP v1.0: MUST be "OKP".
crvstring3Curve. RAMP v1.0: MUST be "Ed25519".
usestring4Intended key use. RAMP v1.0: MUST be "sig".
algstring5Signing algorithm. RAMP v1.0: MUST be "EdDSA".
xstring6base64url-encoded 32-byte Ed25519 public key.
not_beforestring7RFC3339 timestamp. Key is invalid before this instant.
not_afterstring8RFC3339 timestamp. Key is invalid at and after this instant (strict upper bound).

Body served at WBAFile.revocation_url. Snapshot semantics: revoked is the complete set of revoked key thumbprints at as_of; consumers replace their local revocation set on each successful poll.

FieldTypeNumberDescription
as_ofTimestamp1Server's response time (RFC3339, UTC). Consumers use this to detect clock skew.
revokedrepeated string2Complete list of revoked key thumbprints (RFC 7638, base64url-no-pad) at as_of.

Authorizes a third party to push catalog metadata on the provider’s behalf.

FieldTypeNumberDescription
domainstring1Canonical domain of the authorized contributor (e.g., "doubleverify.com").
relationshipstring2Relationship of this contributor to the provider. Examples: "verifier" (resource intelligence vendor that attests to resource properties), "exchange" (an Exchange that enriches catalog entries).

A Exchange authorized to sell this provider’s content.

FieldTypeNumberDescription
domainstring1Canonical domain of the Exchange.
endpointstring2RAMP ExchangeService endpoint URL.
relationshipProviderRelationship3Relationship type (mirrors ads.txt DIRECT/RESELLER).
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Messages for the Agent-to-Broker path (Steps 1 and 6). When an agent talks directly to an Exchange, it uses ResourceQuery/TransactionRequest instead.

Agent sends to Broker (Step 1), carried by BrokerService.Resolve. Pure discovery: it returns offers, executes no transaction, and so carries no idempotency_key (retrying is naturally safe). Correlation rides on the X-Request-ID header, not the body.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
requesterRequester3Requester identity — who is making this request, what scopes they have. The Broker forwards this to Exchanges in ResourceQuery.requester.
urisrepeated string8Resource URIs the agent wants. The Broker forwards these to Exchanges in ResourceQuery.uris. Optional when query / search_filters drive Broker-side discovery instead.
acceptable_restrictionsrepeated AcceptableRestriction9The limits the agent will operate within, per restriction axis — see AcceptableRestriction. The Broker forwards these to Exchanges in ResourceQuery.acceptable_restrictions. Advisory selection inputs, not enforcement.
constraintsoptional RequestConstraints4Constraints for exchange filtering and offer selection.
supported_profilesrepeated string5Domain extension profiles the agent understands. The Broker uses this to: 1. Route queries to Exchanges that support these profiles 2. Forward the profiles in ResourceQuery.supported_profiles 3. Include profile-specific ext fields when returning results Examples: ["ramp-academic-v1"] — agent working on literature review
queryoptional string6Search query for Broker-side resource discovery. Used when the agent doesn't know specific URIs but wants the Broker to find matching resources across Exchanges. When present, the Broker interprets the query and discovers resources across Exchanges on the agent's behalf. Results returned as Offers in DiscoveryResponse, same as for specific URI requests. Can be used alongside uris (specific URIs + search in one request).
search_filtersoptional Struct7Structured search filters (optional, alongside or instead of query). Keys are profile-specific: "academic.topic", "news.category", "legal.jurisdiction", etc. The Broker maps these to Exchange-specific query parameters.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Budget and preference constraints for exchange filtering and offer selection.

FieldTypeNumberDescription
exchangesrepeated string1Authorized Exchange domains. Broker queries only these.
max_priceoptional Cost2Maximum price the agent is willing to pay.
max_unit_costoptional string3Maximum effective cost per unit, as an exact decimal string (not a float).
delivery_preferencerepeated DeliveryMethod4Preferred delivery methods, in order of preference.
reporting_capableoptional bool5Whether the agent supports post-usage reporting.
preferred_exchangesrepeated string6Exchanges the agent has existing relationships with (subscriptions, contracts). The Broker SHOULD prefer these when resource is available — subscription resource has zero marginal cost.
budget_scopeoptional string7Budget scope identifier for per-period tracking. E.g. "user:u-12345" for per-user budgets, "team:eng" for per-team. The Broker tracks cumulative spend per scope across sessions.
period_budgetoptional Cost8Per-period budget limit. The Broker tracks spend against this for the budget_scope. Transactions that would exceed are denied.
budget_periodoptional Duration9Budget period (e.g. "2592000s" = 30 days; proto-JSON encodes Duration as seconds). Resets at period boundary.
max_data_ageoptional Duration10Maximum acceptable age of resource data. The Broker SHOULD exclude offers where (now - Offer.data_as_of) exceeds this duration. Only relevant for DYNAMIC resources. Ignored for STATIC (content is immutable) and LIVE (content doesn't exist yet). Examples: 7 days — "credit report updated within the last week" 1 hour — "stock snapshot from the last hour" 30 days — "drug interaction database updated this month"
max_hopsoptional int3211Maximum forwarding hops the agent will allow (Agent → Broker → … → Exchange), counted as the number of RFC 9421 HTTP Message Signatures on the request. Caps chain depth so a request is not relayed through more brokers than the agent is willing to trust or pay. A Broker MUST NOT forward a request whose signature count would exceed this. Absent = agent imposes no cap (the Exchange's max_intermediary_hops still applies).

Broker returns to Agent (Step 6). Discovery-only: offer_groups (field 4, one OfferGroup per requested URI, each carrying the full signed Offer with Offer.exchange as the execute-routing target) or absence_reason (field 16) with empty offer_groups. There are no inline delivery fields — the per-transaction result rides on TransactionResponse via the separate execute path.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
offer_groupsrepeated OfferGroup4Offers grouped by requested URI — the sole offer representation in this response. One OfferGroup per URI the agent asked for (echoed in OfferGroup.uri); a group with no offers carries OfferGroup.absence_reason explaining why. Each contained Offer is the full signed Offer the Exchange issued (including Offer.exchange, the execute-routing target), forwarded by the Broker unchanged so the agent can verify the signature end to end.
absence_reasonoptional OfferAbsenceReason16Why the resolve produced no offers at all. Set (and offer_groups empty) on a successful "no result" answer; unset when offer_groups is non-empty. Same vocabulary DiscoverResources uses for OfferGroup.absence_reason. RESTRICTION_FILTERED may appear here, but Resolve does not surface the per-axis detail: DiscoveryResponse has no restriction_filters companion (unlike OfferGroup). A consumer needing the filtered axes calls DiscoverResources. Existence-oracle note: an authorization-flavored reason (SCOPE_INSUFFICIENT, NOT_AUTHORIZED, NOT_IN_CATALOG, CONTENT_BLOCKED) confirms a resource exists and why access was refused. Resolve surfaces the same oracle at the broker that OfferGroup.absence_reason does at the Exchange, so the same mitigation applies: where existence itself must stay hidden, the Broker MAY omit the reason (leave this unset) rather than reveal it. See the threat model.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

Messages for the optional CatalogService RPC.

Push or update content entries in the Exchange catalog.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
tenant_idstring2Tenant identifier
entriesrepeated ResourceEntry3Content entries to push
caller_idstring4Identity of the caller (who is pushing this data). The Exchange verifies this matches a registered CatalogService client.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

A single resource catalog entry.

FieldTypeNumberDescription
domainstring1Provider domain
pathstring2Content path
content_idoptional string3Content identifier
titleoptional string4Content title
word_countoptional int325Word count
estimated_quantityoptional int326Estimated quantity in the metering unit
content_hashoptional string7Content hash
hash_methodoptional string8Hash algorithm
sourceoptional IngestionSource9How the entry was discovered
provenance_sourceoptional string10Who provided this resource metadata. Creates audit trail for "where did this catalog entry come from?"
provenance_timestampoptional Timestamp11When this metadata was collected/generated.
attestationsrepeated ResourceAttestation12Signed attestations about this resource entry. Same semantics as Offer.attestations — see ResourceAttestation message for verification levels and claim vocabulary. Attestations pushed via CatalogService are verified at push time: the Exchange checks that the attestation verifier is authorized to push for this provider (via catalog_contributors in the provider's WellKnownManifest) and validates the attestation signature against the verifier's public key from their /.well-known/ramp.json endpoint (WellKnownManifest, role determined by the verifier's operator).
termsrepeated LicenseTerm13Publisher-declared licensing terms for this resource. See LicenseTerm for the full model. For ENUMERATED terms, Pricing MUST be present. For REFERENCE_ONLY terms, License.uri is authoritative. The Exchange validates ENUMERATED terms at push time and surfaces them in Offer.terms on discovery.
resource_mutabilityoptional ResourceMutability14Optional mutability hint. When omitted, the Exchange applies the STATIC default at Offer build; an explicit UNSPECIFIED is rejected. A value in ext is not read — the typed field is authoritative, so an ext-only value is treated as omitted. Mirrors the required Offer-side ResourceIdentity.resource_mutability.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.

The accepted / rejected counts are entry-level tallies of a successful push — not the removed failure bools. A push that could not be applied at all travels as a non-OK transport error carrying ErrorDetail.catalog_rejection.

FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
acceptedint322Number of entries accepted
rejectedint323Number of entries rejected
warningsrepeated string4Non-fatal issues encountered during ingestion. Examples: unrecognized vocab token in a Restriction (term accepted but flagged), REFERENCE_ONLY term missing License.uri (informational). Warnings do not cause rejection — they are surfaced so publishers can fix their feeds without a hard failure.
extStruct15Extension point
ext_criticalrepeated string90Critical extension keys (COSE crit pattern, RFC 9052). Lists keys within ext that the consumer MUST understand. Unknown keys in this list → reject with UNKNOWN_CRITICAL_EXTENSION. Empty (default) → all ext keys are safe to ignore.
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
tenant_idstring2Tenant identifier
pathsrepeated string3Paths to remove
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
removedint322Number of entries removed
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
tenant_idstring2Tenant identifier
FieldTypeNumberDescription
verstring1RAMP protocol version — "1.0". Stamped by the sender from a single constant; advisory on receive. See "Protocol version" in the file header.
startedbool2Whether the refresh was started

A resource carries zero or more LicenseTerm entries — each term is a complete commercial arrangement. Multiple terms are the normal case: a news article may be free for academic use and paid for commercial use; a stock photo may be perpetually licensed with an impressions cap.

See /protocol/licensing-terms for a full conceptual walkthrough with examples.

One complete access arrangement for a resource. Lives at both ingestion (ResourceEntry.terms) and emission (Offer.terms).

Validation rules (wire-enforced via protovalidate unless noted). A parenthetical code is the cross-field CEL rule id: that enforces the rule (e.g. license_term.reference_only.requires_uri); single-field rules use protovalidate’s standard constraints (enum.not_in, string.pattern, …).

  • pricing MUST be present on every term, any semantics — absent Pricing is a validation error. model = FREE must be stated explicitly — absent Pricing is not free.
  • semantics MUST be set — TERM_SEMANTICS_UNSPECIFIED is rejected (the field’s enum.not_in:[0] rule).
  • REFERENCE_ONLY requires license.uri to be non-empty (license_term.reference_only.requires_uri); a License with a uri requires a uri_digest (license.digest_required_with_uri).
  • At most one Restriction per kind (license_term.one_restriction_per_kind); a token cannot be both permitted and prohibited (restriction.permitted_prohibited_disjoint).
  • Unknown tokens in restrictions[].permitted / prohibited produce PushResourcesResponse.warnings[] but do NOT cause hard rejection (ingest-time, not CEL).
FieldTypeNumberDescription
licenseoptional License1Governing license document. Authoritative for REFERENCE_ONLY terms, which MUST carry a License with a non-empty uri — a REFERENCE_ONLY term that references nothing is rejected at ingest.
semanticsTermSemantics2How to interpret the machine fields.
restrictionsrepeated Restriction3Usage restrictions (function, geography, user-type). Multiple restrictions are AND-combined — the agent must satisfy all of them.
quotasrepeated Quota4Usage caps. The agent must not exceed any individual Quota.
obligationsrepeated Obligation5Post-use behavioral requirements.
pricingoptional Pricing6Pricing for this term. REQUIRED for every term regardless of semantics — an agent cannot act on a priceless term, so absent Pricing is a validation error at ingest. model = FREE must be stated explicitly (absent Pricing is not free). A REFERENCE_ONLY term states its price here too; its License governs the human-readable terms but does not replace the machine-readable price.
scopesrepeated string7Delegation scope-gating: the Exchange returns this term to an agent iff the agent's delegation grant covers ALL of these scopes (AND-semantics). Empty = public. A subscription term is Pricing{model:FREE} + scopes:["subscription:..."]. Coverage uses the SAME matching rule as Requester/delegation scopes: segment-wise (":" separated), each granted segment must equal the corresponding required segment or be "", a terminal "" matches all remaining segments, and there is NO implicit prefix match (a grant narrower than the requirement does not cover it). "dist:*" covers "dist:US" and "dist:US:CA"; "dist" covers only "dist". There is exactly one scope-matching algorithm across the protocol.
part_labeloptional string8Informational human-readable name for this sub-part (sub-part terms).

Identifies the governing license document for a LicenseTerm.

FieldTypeNumberDescription
urioptional string1Canonical identity of the license document (RFC 3986). MUST NOT be URL-validated — data-labels TDL identifiers use non-URL schemes. For REFERENCE_ONLY terms this is the authoritative specification. Examples: "https://creativecommons.org/licenses/by/4.0/" "https://techcrunch.com/licensing/ai-terms-2026" "MUST NOT URL-validate" means do not REJECT non-URL schemes — it does NOT mean fetch blindly. A consumer that dereferences this URI MUST apply the SSRF countermeasures in the security threat model (T-LIC-1): scheme allowlist, block loopback/private/metadata addresses (resolve-then-check), fetch via an egress proxy, and treat the response as untrusted content. Verify the fetched bytes against uri_digest before use.
idoptional string2Stable short identifier: SPDX short-id ("GPL-3.0-only"), TollBit cuid, or catalog doc-id. Used by agents and the vocab linter for known-license lookup; SHARE_ALIKE derivatives default their scope_license to this.
nameoptional string3Human-readable name (licenseType, schema.org node name).
immutableoptional bool4Data-labels TDL: the document at uri is versioned and will not change.
uri_digestoptional string5Cryptographic digest of the document at uri, in "method:hexdigest" form (e.g. "sha256:9f86d081..."). Pins the referenced document so a consumer can verify the bytes it fetches match what was offered; covered by the offer signature, so it is tamper-evident end to end. REQUIRED whenever uri is non-empty — any semantics, mutable or not: without a pinned digest a MitM (or the publisher) can swap the document the agent reads. The Exchange pins it at ingestion (computing it over the safely-fetched document, or accepting a publisher-supplied value when uri is not HTTP-fetchable, e.g. a non-URL TDL scheme). The method MUST be a collision-resistant hash — sha256, sha384, or sha512. Legacy md5/sha1 are rejected on the wire: a forgeable digest would defeat the swap-protection this field exists for. The CEL is STRUCTURE ONLY (allowlisted prefix + matching hex length); presence (digest-when-uri) is enforced at ingest.

A single constraint on one licensing dimension: function (what), geography (where), or user-type (who).

Reading a restriction: a value is in-scope when it matches at least one permitted[] token AND none of the prohibited[] tokens. Empty permitted[] = any value permitted on this axis. Restrictions ride on the offer; the agent self-selects the term it can honour (the Exchange does not pre-filter terms against requester attributes).

Vocabulary sources: proto-native — (ramp.v1.vocab_enum) on the RESTRICTION_KIND_FUNCTION / RESTRICTION_KIND_GEOGRAPHY / RESTRICTION_KIND_USER_TYPE enum values (no side-car JSON registry).

FieldTypeNumberDescription
kindRestrictionKind1Which dimension this restriction applies to.
permittedrepeated string2Tokens allowed on this axis. Empty = all permitted. For FUNCTION: "ai-input", "ai-train", "search", "editorial", "commercial", … For GEOGRAPHY: "US", "DE", "EU", "EEA", "*", … For USER_TYPE: "individual", "academic", "commercial_entity", …
prohibitedrepeated string3Tokens blocked on this axis. Takes precedence over permitted[].
advisorybool4Fail-closed by default. When false (the default), this restriction is BINDING: an agent that cannot evaluate every token in it — including an unknown vendor token — MUST decline the term. Set advisory = true to downgrade an unverifiable restriction to non-blocking. This deliberately inverts the COSE-crit opt-in default: a license restriction a consumer does not understand should stop it, not be silently ignored.

A usage cap that gates whether a LicenseTerm remains valid. Quotas limit consumption before a term expires or must be renegotiated — they are NOT billing quantities.

Metric vocabulary: proto-native — (ramp.v1.vocab) on Quota.metric. The registered metrics, rendered from the proto at build time:

display-words impressions tokens input-tokens units-manufactured accesses copies seats

FieldTypeNumberDescription
metricstring1The unit being capped — an open vocabulary axis. The (ramp.v1.vocab) entries below are the SOLE authored source of the registered bare metric tokens. A buf plugin reads them structurally and emits the quotametrics constants + IsRegistered; ingest enforces membership from those. The CEL is STRUCTURE ONLY (non-empty bare token or vendor:namespaced) — it never lists the tokens, so it cannot drift. Token meanings: display-words Words of content text rendered to an end user. impressions Times the content is displayed to an end user. tokens LLM output tokens generated using this content. input-tokens LLM input tokens consumed from this content. units-manufactured Physical units manufactured from this design/pattern. accesses Distinct content access / retrieval events. copies Digital or physical copies produced. seats Distinct named users licensed to access the content.
limitint642Maximum allowed value in the given window. A quota of 0 grants nothing — express "no access" by omitting the term, not a zero quota.
windowQuotaWindow3Time window over which the limit accumulates.

A post-use behavioral requirement attached to a LicenseTerm. Attribution and contribution are behavioral requirements here, not pricing models.

FieldTypeNumberDescription
kindObligationKind1What the agent must do.
triggerObligationTrigger2When the obligation activates.
scope_licenseoptional License3The license that derivatives must be released under. REQUIRED for SHARE_ALIKE (rejected if absent), where it MUST identify a license — set id (SPDX short-id, the common copyleft case, often the term's own License.id) and/or uri. Because it is a License, a referenced uri inherits the uri_digest swap-protection rule: a uri without a digest is rejected, exactly as for any other license reference.
detailoptional string4Free-form detail: attribution string, notice file URI, etc. OBLIGATION_KIND_OTHER without it → lint warning.

One way to communicate failure across every RPC. The transport carries a coarse canonical code (gRPC / Connect Code) as the error class; an ErrorDetail message — attached to the non-OK transport error’s details (the same mechanism protovalidate uses to attach its Violations) — carries the precise, machine-readable reason and structured context. Clients branch on the typed reason, never on a human string.

Error vs. body. A query that ran successfully returns its answer in the response body, and “no results” / per-item absence (OfferGroup.absence_reason) is a success, not an error. Only a method that could not perform the requested action returns a non-OK code plus an ErrorDetail. The per-domain reason enums below are the single source of truth that replaces the former in-body failure fields (denial_reason, rejection_reason, accepted, verified, failure_reason).

The structured detail attached to every non-OK transport error.

FieldTypeNumberDescription
messagestring1Developer-facing, NON-authoritative human message. Clients MUST branch on the typed reason below, never on this text. Servers SHOULD NOT place secrets, PII, or existence/authorization detail here that the closed typed reason deliberately withholds: unlike the enum, this free text is unbounded and easily becomes an existence oracle or leak channel (see metadata).
domainstring2Stable grouping for the failing surface, e.g. "ramp.v1.ExchangeService". Mirrors google.rpc.ErrorInfo.domain so generic tooling can group errors.
metadatamap<string, string>3Dynamic key/value context that also appears in message (ids, limits, axes). Mirrors google.rpc.ErrorInfo.metadata. Strongly-typed context rides in the per-domain reason block below instead. Same leakage rule as message: servers SHOULD NOT put secrets, PII, or withheld existence/authorization detail here — it is the same potential side channel as the absence oracle.
transaction_denialTransactionDenial10reason oneof — ExecuteTransaction denial
catalog_rejectionCatalogRejection11reason oneof — CatalogService rejection
registration_failureRegistrationFailure12reason oneof — agent/provider registration refused
dispute_failureDisputeFailure13reason oneof — DisputeTransaction filing refused
domain_verification_failureDomainVerificationFailure14reason oneof — domain verification failed
retrieval_auth_failureRetrievalAuthFailure15reason oneof — signed-URL / proof-of-possession check failed
usage_report_rejectionUsageReportRejection16reason oneof — ReportUsage filing rejected

Exactly one typed reason block is set, selected by the failing method. The reason oneof is absent for generic transport-class failures (e.g. INVALID_ARGUMENT, INTERNAL) that carry no domain-specific reason.

ExecuteTransaction could not complete. Reuses the DenialReason vocabulary.

FieldTypeNumberDescription
reasonDenialReason1The denial reason (defined-only, non-zero)
restriction_mismatchesrepeated RestrictionKind2When reason = RESTRICTION_NOT_SATISFIED, the failed axes (same RestrictionKind vocabulary the terms use).
offer_idoptional string3Batch mode: the offer this denial pertains to.

A CatalogService call could not be applied.

FieldTypeNumberDescription
reasonCatalogRejectionReason1The rejection reason (defined-only, non-zero)
rejected_pathsrepeated string2For partial-batch failures: the entry paths that were rejected.

A registration request could not be completed.

FieldTypeNumberDescription
reasonRegistrationFailureReason1The failure reason (defined-only, non-zero)
field_errorsrepeated RegistrationFieldError2When reason = INVALID_REGISTRATION_DATA: the registration_data members that are missing or do not conform. Empty for every other reason.

One registration_data member that failed the Exchange’s published registration_schema, carried on RegistrationFailure.field_errors.

FieldTypeNumberDescription
pathstring1RFC 6901 JSON Pointer to the offending member, relative to registration_data (e.g. "/vat_id", "/address/postal_code"). The empty string addresses registration_data itself, for whole-object failures (oneOf, minProperties) that belong to no single member.
errorstring2Developer-facing, NON-authoritative description of what failed (e.g. "required", "must match ^[A-Z]{2}[0-9]+$"). Wording is validator-defined and not stable across Exchanges; clients branch on reason, never on this text. States the constraint, NEVER the submitted value — the ErrorDetail leakage rule applies here too.

A dispute could not be filed (distinct from DisputeReason, why the agent disputes, and DisputeStatus, an accepted dispute’s lifecycle).

FieldTypeNumberDescription
reasonDisputeFailureReason1The failure reason (defined-only, non-zero)

RequestDomainVerification / ConfirmDomainVerification failed.

FieldTypeNumberDescription
reasonDomainVerificationFailureReason1The failure reason (defined-only, non-zero)

A signed-URL retrieval or its proof-of-possession check failed at the delivery edge.

FieldTypeNumberDescription
reasonRetrievalAuthFailureReason1The failure reason (defined-only, non-zero)

A usage report could not be accepted.

FieldTypeNumberDescription
reasonUsageReportRejectionReason1The rejection reason (defined-only, non-zero)
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1NOT_CATALOG_CONTRIBUTORcaller is not an authorized contributor for the domain
2TENANT_MISMATCHtenant_id does not match the authenticated caller
3DOMAIN_NOT_VERIFIEDcontributing domain is not verified
4SIGNATURE_INVALIDrequest signature missing or invalid
5MALFORMED_ENTRYa resource entry failed schema/validation
6UNKNOWN_VOCAB_TOKENan unregistered vocab token in a restriction/term
7QUOTA_EXCEEDEDcontributor push quota exceeded (per-caller)
8TERMS_LIMIT_EXCEEDEDa single entry carries more license terms than allowed (per-entry cap)
9URI_UNAVAILABLEThe URI cannot be claimed by this caller's entries. Named from the caller's own perspective ON PURPOSE: it MUST NOT disclose that another resource/ contributor already owns the URI. Within one publisher, mutually-untrusting contributors share a catalog, so an "owned by another" reason would be a confirmed-existence oracle a contributor could use to map a competitor's catalog. The conflict is resolvable only by the publisher (who is authorized to see full ownership); the human-readable message routes the caller there without confirming who, if anyone, holds the URI.
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1DOMAIN_NOT_VERIFIEDcaller domain is not verified
2INVALID_KEYsigning key malformed or unsupported
3SIGNATURE_INVALIDrequest signature invalid
4ALREADY_REGISTEREDidentity already registered
5QUOTA_EXCEEDEDregistration quota exceeded
6INVALID_REGISTRATION_DATAregistration_data does not conform to the Exchange's published registration_schema
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1TRANSACTION_NOT_FOUNDtransaction_id is unknown
2REPORT_NOT_FILEDno UsageReport precedes the dispute (report_id missing/unknown)
3WINDOW_EXPIREDfiled outside the allowed dispute window
4DUPLICATEa dispute already exists for this transaction
5INELIGIBLEthe transaction/state is not disputable
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1CHALLENGE_NOT_FOUNDtoken not served at the well-known path
2CHALLENGE_MISMATCHserved token does not match the issued token
3CHALLENGE_EXPIREDconfirmation arrived after the challenge expired
4FETCH_FAILEDExchange could not fetch the verification URL
5EXCHANGE_NOT_AUTHORIZEDramp.json does not list this Exchange
6KEY_REGISTRATION_FAILEDsigning-key registration failed during confirmation

Single-sources the delivery-edge token unions (signed-URL checks in verify.ts, RFC 9421 proof-of-possession in pop.ts).

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1URL_EXPIREDSigned-URL checks (verify.ts).
2URL_SIGNATURE_MISSING'missing_sig'
3URL_EXPIRY_MISSING'missing_exp'
4URL_SIGNATURE_MISMATCH'signature_mismatch'
5AGENT_KEY_MISSINGProof-of-possession checks (pop.ts).
6PROOF_SIGNATURE_MISSING'missing_sig'
7KEYID_MISMATCH'keyid_mismatch'
8THUMBPRINT_MISMATCH'thumbprint_mismatch'
9PROOF_CREATED_MISSING'pop_missing_created'
10PROOF_EXPIRY_MISSING'pop_missing_exp'
11PROOF_EXPIRED'pop_expired'
12PROOF_SIGNATURE_INVALID'pop_sig_invalid'
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1TRANSACTION_NOT_FOUNDtransaction_id is unknown
2DUPLICATEa report was already filed for this transaction
3WINDOW_EXPIREDfiled outside the reporting window
4MISSING_REQUIRED_FIELDSReportingObligation.required_fields not satisfied
5MALFORMEDreport payload failed validation

The charging structure only (a closed set). The open-ended metering basis (“per what”) is NOT enumerated here — it lives in Pricing.unit as a registry-governed vocabulary. UNSPECIFIED is rejected on Pricing.model (omission cannot default to FREE).

ValueNameDescription
0UNSPECIFIEDunset — zero allowed on WellKnownManifest.pricing_models_supported (capability list); rejected (not_in:[0]) as the Pricing.model discriminator (omission cannot default to FREE)
1FREEno charge; rate must be 0 (state FREE explicitly — absent Pricing is not free)
2PER_UNITrate per Pricing.unit; unit REQUIRED (registered token or vendor:custom)
3FLATone-time flat fee; rate is the total, no unit

The metering basis (“per what”) is the Pricing.unit vocabulary, not a model; a subscription is FREE + scopes; attribution and contribution are Obligation.kinds; revenue-share settlement is off-protocol.

Registered Pricing.unit tokens (the metering basis — rendered from the proto, any vendor:namespaced token also accepted):

fetches accesses tokens calls pages seconds minutes records streams images seats units-manufactured characters bytes items sq-km

How usage is tracked for billing reconciliation. Used in Pricing.metering (field 9). Absent = ONLINE.

ValueNameDescription
0ONLINEDefault. Exchange tracks usage events in real time. ReportUsage is required.
1NONEOne-time perpetual sale. No ongoing metering; billing_id is issued at ExecuteTransaction and the ledger entry is closed. No ReportUsage required.
2OFFLINE_SELF_REPORTEDAgent self-reports physical-world consumption (e.g. units manufactured from a licensed design). Exchange audits.

How the Exchange interprets a LicenseTerm’s machine fields.

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1ENUMERATEDMachine restrictions/quotas/obligations are the complete, authoritative expression of the term (internally consistent, no self-contradiction) and are enforced. Pricing MUST be present.
2REFERENCE_ONLYThe document at License.uri (MUST be non-empty) is the authoritative, complete source; the agent reads it before using. Machine restrictions/quotas/obligations are optional here (the publisher MAY send Pricing alone) but any that are sent must be accurate (MUST NOT contradict the referenced document) and are enforced just like ENUMERATED. Pricing is still required.

Which dimension a Restriction constrains.

ValueNameDescription
0UNSPECIFIEDunset — zero allowed on AcceptableRestriction.axis / OfferGroup.restriction_filters / *.restriction_mismatches; rejected (not_in:[0]) as the Restriction.kind discriminator
1FUNCTIONWhat the agent may do with the content. Seeded from RSL 1.0 AI-use vocabulary and extended with established IP/copyright terms.
2GEOGRAPHYWhere the agent may use the content. ISO 3166-1 alpha-2 codes (US, DE, GB) are valid structurally; only the non-ISO specials are registered here.
3USER_TYPEWho may access and use the content.
4OTHERCustom axis; values carried in permitted/prohibited

The complete token list for each axis, rendered directly from the proto’s (ramp.v1.vocab_enum) options at build time — not hand-maintained here, so it cannot drift from the contract. Any vendor:namespaced token is also accepted on every axis; these are the registered bare tokens.

FUNCTION — what the agent may do:

all ai-all ai-train ai-input ai-index search crawl text-and-data-mining tts commercial advertising editorial research reproduce distribute modify display sync broadcast stream print manufacture sell

GEOGRAPHY — registered specials (plus structural ISO 3166-1 alpha-2 codes):

* EU EEA

USER_TYPE — what kind of entity the agent represents:

individual academic non_profit news_publisher broadcaster commercial_entity

Time window over which a Quota.limit accumulates.

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1HOURLYResets each hour
2DAILYResets each day
3MONTHLYResets each month
4TOTALLifetime cap — never resets

What the agent must do after use. ATTRIBUTION and CONTRIBUTION are behavioral requirements, not pricing models.

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1ATTRIBUTIONCredit the author or publisher whenever the resource is used
2CONTRIBUTIONGood-faith payment — amount suggested, not contractually fixed
3SHARE_ALIKEDerivatives must be released under the same / compatible license (CC-BY-SA / GPL style); scope_license required
4NETWORK_COPYLEFTNetwork service triggers copyleft (AGPL style)
5NOTICEInclude the specified copyright notice
6OTHERCustom requirement, described in Obligation.detail

When an Obligation activates.

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1ON_USETriggered on any use
2ON_DISTRIBUTIONTriggered when copies are distributed
3ON_NETWORK_SERVICETriggered when served over a network (AGPL)
4ON_DERIVATIVETriggered when a derivative work is produced
ValueNameDescription
0UNSPECIFIEDoutput enum; zero = not-applicable on TransactionResultItem.denial_reason, rejected (not_in:[0]) where set on TransactionDenial.reason
1BILLING_REF_INACTIVEthe requester's account (the billing_ref minted at Register) is not active / not recognized by the billing system
2INSUFFICIENT_BALANCERequester's balance too low
3RATE_LIMITEDToo many requests
4CONTENT_UNAVAILABLEResource no longer available
5RESTRICTION_NOT_SATISFIEDAccepted term's restriction not satisfied by the request; the axes are in TransactionDenial.restriction_mismatches (single) / TransactionResultItem.restriction_mismatches (batch), same RestrictionKind vocabulary as the terms
6REPORTING_OVERDUERequester has >20% overdue reports (MAY threshold)
7OFFER_EXPIREDOffer TTL exceeded
8SIGNATURE_INVALIDOffer signature verification failed
9QUOTA_EXCEEDEDSubscription access count exhausted for this period
10DELEGATION_INVALIDDelegation missing, unverifiable, expired, holder binding failed, or scopes/caps do not cover the request
11SCOPE_INSUFFICIENTRequester scopes don't cover this resource
12ENTITLEMENT_MISSINGEntitlement family — subscription/entitlement access failures on a subscription-gated offer. Finer-grained than DELEGATION_INVALID so callers and operator tooling can triage each mode. These single-source the Exchange's KindEntitlement* refusal taxonomy, which today is distinguishable only by a server-side tag (all collapse to UNAUTHENTICATED on the wire). Format-neutral: they classify a JWT/opaque entitlement-token failure, not a format-specific one.
13ENTITLEMENT_MALFORMEDentitlement token failed to decode (malformed)
14ENTITLEMENT_EXPIREDentitlement token's validity window has passed
15ENTITLEMENT_WRONG_BUYERtoken's subscriber_org does not match the asserted requester
16SUBSCRIPTION_LAPSEDthe covering subscription contract has lapsed
17ENTITLEMENT_NOT_GRANTEDsubscription exists but no buyer-side grant ties this caller to it
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1CONTENT_MISMATCHContent hash does not match what was promised in the Offer.
2DELIVERY_FAILEDResource was not delivered (signed URL returned 404/403/5xx).
3WRONG_CONTENTResource was delivered but is entirely different from what was described.
4EXPIRED_BEFORE_FETCHSigned URL expired before the agent could fetch the resource.
5INCOMPLETE_CONTENTResource was truncated or incomplete.

Full dispute lifecycle from filing to final resolution.

ValueNameDescription
0UNSPECIFIEDunset — output/optional; zero is a valid not-applicable/unset state
1FILEDAgent submitted DisputeRequest. Initial state.
2AUTO_RESOLVEDExchange auto-resolved via Tier 1 rules (CDN logs, hash comparison).
3EVIDENCE_NEEDEDExchange requests additional evidence from the agent or provider.
4UNDER_REVIEWExchange is reviewing with Tier 2 resolution rules.
5ESCALATEDEscalated to Tier 3 pattern-based investigation.
6RESOLVEDDecision made (credit, redelivery, rejected). See resolution field.
7APPEALEDLosing party appealed with new evidence. Re-enters review.
8SETTLEDFinancial settlement applied.
9FINALNo further appeals. Dispute closed.

Outcome of a resolved dispute.

ValueNameDescription
0UNSPECIFIEDunset — output/optional; zero is a valid not-applicable/unset state
1CREDITAccount credit applied to the agent's next billing cycle.
2REDELIVERYNew signed URL issued for the same resource (e.g., when content hash now matches after provider correction).
3REJECTEDDispute reviewed and rejected; no remedy applied.
4INVESTIGATIONEscalated to Tier 3 pattern analysis for further investigation.

How the citation is presented to the user.

ValueNameDescription
0LINKHyperlink citation
1FOOTNOTEFootnote citation
2INLINEInline text citation

Why no offers are available for a requested URI.

ValueNameDescription
0UNSPECIFIEDunset — output/optional; zero is a valid not-applicable/unset state
1NOT_IN_CATALOGResource URI is not in this Exchange's catalog.
2CONTENT_BLOCKEDResource exists but the provider has opted out of AI access for it (the provider's consent/opt-out signal blocks licensing).
3RESTRICTION_FILTEREDResource exists but its offers were pre-filtered out for one or more restriction axes the requester stated (a convenience filter matched to the query, not an enforcement verdict — see Restriction). The filtered axes are listed in OfferGroup.restriction_filters, in the same RestrictionKind vocabulary the terms use. The agent MAY still be eligible.
4TEMPORARILY_UNAVAILABLEResource is temporarily unavailable (e.g., provider feed refresh in progress).
5NOT_AUTHORIZEDExchange is not authorized by the provider to sell this resource.
6SCOPE_INSUFFICIENTRequester's scopes/subscription do not cover this resource. Applies wherever access is gated by subscription or scope entitlements (not only enterprise deployments): the resource exists but the requester's delegation token or subscription does not grant it. The Exchange returns this so the requester learns the resource is reachable under the right subscription/scope. (Where existence itself must stay hidden, the Exchange MAY omit it silently instead.)
7UNKNOWN_CRITICAL_EXTENSIONConsumer encountered ext_critical keys it does not recognize. The unrecognized keys SHOULD be listed in the OfferGroup's ext field under "unrecognized_critical_extensions" for diagnostic purposes.
8BUDGET_EXCEEDEDOffers exist, but none fit within the requester's budget (e.g. every offer's price exceeds RequestConstraints.period_budget). Returned by Resolve as a successful "no result" answer when a budget/price ceiling filtered out every otherwise-licensable offer.

What kind of entity is making the request.

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1AGENTAutonomous AI agent (LLM, RAG system, research bot).
2HUMAN_TOOLHuman using an AI-powered tool (copilot, assistant).
3SERVICEEnterprise service account (automated pipeline, cron job).
4DELEGATEDAgent acting on behalf of a user (delegated identity).
5RESEARCHResearch pipeline (batch data collection, model training).

Identifies which RAMP participant a WellKnownManifest describes.

ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1AGENT
2EXCHANGE
3BROKER
4PUBLISHER
ValueNameDescription
0UNSPECIFIEDunset — output/optional; zero is a valid not-applicable/unset state
1EXCHANGEURI was requested by the agent directly or found via Exchange query.
2SEARCHURI was discovered via a search engine (e.g., Exa, Tavily, Brave Search). The Broker searched on the agent's behalf, then routed through Exchange.
3RECOMMENDATIONURI was recommended by a resource recommendation service.
4SYNDICATIONURI was found via resource syndication tracking (e.g., same article on another domain).
ValueNameDescription
0UNSPECIFIEDunset — output/optional and capability-list; zero is a valid not-applicable/unset state
1DIRECTExchange returns resource inline or via its own endpoint.
2INSTRUCTIONSExchange returns access info (signed URL, token) for retrieval from a Resource Owner / Resource Delivery Endpoint.
3STREAMINGResource delivered via real-time streaming connection (WebSocket, SSE, gRPC stream). The signed URL points to a streaming endpoint. Agent connects and receives continuous data for the duration of the session.

Signals whether resource content changes over time. Drives hash verification behavior.

ValueNameDescription
0UNSPECIFIEDunset — the Exchange defaults to STATIC at Offer build; an explicit UNSPECIFIED is rejected on ResourceEntry.resource_mutability and the Offer's ResourceIdentity.resource_mutability (both {not_in:[0]})
1STATICContent is immutable. Hash computed at offer time will match at delivery time. Agent SHOULD verify content_hash on delivery. Mismatch is disputable.
2DYNAMICContent changes between offer generation and agent fetch. Hash reflects state at offer time — mismatch is expected, not disputable. Offer.data_as_of indicates when the snapshot was taken.
3LIVEContent does not exist at offer time (real-time streaming). No content_hash is applicable. The "resource" is the stream endpoint/channel. Metering is time-based (per-minute, per-hour).
ValueNameDescription
0UNSPECIFIEDunset — output/optional; zero is a valid not-applicable/unset state
1RAMP_SITEMAPRAMP XML namespace in sitemap
2RSLRSL rsl.txt
3SITEMAPStandard sitemap.xml
4HTML_CRAWLHTML crawl + readability extraction
5CMS_APICMS REST API (WordPress, etc.)
6MANUALManual configuration
7CATALOG_APIThird-party CatalogService push
ValueNameDescription
0UNSPECIFIEDunset — rejected at ingest
1DIRECTProvider has a direct contract with this Exchange.
2RESELLERExchange resells resources via another authorized party.

Authentication methods a participant advertises in its WellKnownManifest.

ValueNameDescription
0UNSPECIFIEDunset — zero allowed on WellKnownManifest.supported_auth_methods (capability list); no discriminator carrier
1GNAPGNAP (RFC 9635) — key-first identity, key-bound tokens. Recommended.
2OAUTH_DPOPOAuth 2.0 + DPoP (RFC 9449) — sender-constrained tokens. Enterprise recommended.
3OAUTH_BEAREROAuth 2.0 Bearer JWT — acceptable, widely deployed.
4OAUTH_MTLSOAuth 2.0 + mTLS — high-security environments.

C2PA / content-provenance status carried on ResourceIdentity.

ValueNameDescription
0C2PA_STATUS_UNSPECIFIEDunset — output/optional; zero is a valid not-applicable/unset state
1C2PA_STATUS_TRUSTEDManifest is valid AND signer certificate chains to a C2PA Trust List root. Highest assurance: provenance is cryptographically verified by a trusted CA.
2C2PA_STATUS_VALIDManifest is structurally correct and signature verifies, but signer certificate does NOT chain to a C2PA Trust List root. The content has provenance, but the signer is not institutionally vouched for.
3C2PA_STATUS_INVALIDManifest is present but validation failed (signature mismatch, malformed JUMBF, certificate expired, hard binding broken).
4C2PA_STATUS_ABSENTContent was checked and has no C2PA manifest.