Skip to content

Exchange Manifest

An Exchange describes itself with a WellKnownManifest carrying role=ROLE_EXCHANGE. Analogous to OIDC Discovery (/.well-known/openid-configuration), it enables automated discovery and capability negotiation by Brokers and agents.

The manifest answers: “What can this Exchange do, where are its endpoints, which keys sign its offers, and what capabilities does it support?”

Endpoint: https://{domain}/.well-known/ramp.json — the single canonical file every RAMP participant serves, differentiated by role.

PropertyValue
TransportTLS required (HTTPS)
AuthenticationNone (public endpoint)
Cache-Controlmax-age=3600, must-revalidate — keys carry their own not_before/not_after; use the invalidation_url channel for emergency revocation
Content-Typeapplication/json
GenerationStatic JSON from config at startup
{
"ver": "1.0",
"role": "ROLE_EXCHANGE",
"domain": "exchange.example.com",
"name": "Example Content Exchange",
"operator": "Example Media Corp",
"operator_domain": "examplemedia.com",
"endpoint": "https://exchange.example.com/exchange/v1",
"public_keys": [
{
"kid": "exchange-2026-q2",
"kty": "OKP",
"crv": "Ed25519",
"use": "sig",
"alg": "EdDSA",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
"not_before": "2026-04-01T00:00:00Z",
"not_after": "2026-10-01T00:00:00Z"
}
],
"invalidation_url": "https://exchange.example.com/.well-known/ramp-invalidations.json",
"health_endpoint": "https://exchange.example.com/healthz",
"catalog_endpoint": "https://exchange.example.com/catalog/v1",
"protocol_versions_supported": ["1.0"],
"pricing_models_supported": [
"free",
"per_unit",
"flat"
],
"delivery_methods_supported": [
"direct",
"instructions",
"streaming"
],
"supported_profiles": [
"ramp-academic-v1",
"ramp-news-v1"
],
"base_currency": "USD",
"hash_methods_supported": [
"sha-256",
"sha-384"
],
"accepted_verifiers": [
"doubleverify.com",
"integralads.com"
],
"supported_auth_methods": ["gnap", "oauth_dpop"],
"oidc_issuer": "https://exchange.example.com",
"contact": "ramp-integration@examplemedia.com",
"terms_uri": "https://examplemedia.com/ramp-terms",
"privacy_uri": "https://examplemedia.com/privacy"
}
FieldTypeRequiredDescription
verstringYesRAMP protocol version ("1.0")
rolestringYesROLE_EXCHANGE for an Exchange manifest
domainstringYesCanonical domain of this Exchange
namestringNoHuman-readable Exchange name
operatorstringNoOrganization operating this Exchange
operator_domainstringNoOperator’s corporate domain
endpointstringNoExchangeService endpoint URL
public_keysobject[]YesInline RFC 7517 JWKs (Ed25519) that sign this Exchange’s offers; ≥1 valid at serve time
invalidation_urlstringNoEmergency key-revocation list URL (KeyInvalidationList); serve short/no-store
health_endpointstringNoHealth check endpoint URL
catalog_endpointstringNoCatalogService endpoint URL
protocol_versions_supportedstring[]NoSupported RAMP protocol versions
pricing_models_supportedstring[]NoSupported pricing models
delivery_methods_supportedstring[]NoSupported delivery methods
hash_methods_supportedstring[]NoAccepted content hash methods
accepted_verifiersstring[]NoTrusted attestation verification vendor domains
supported_auth_methodsstring[]NoAuthorization methods supported (ordered by preference)
oidc_issuerstringNoOIDC Discovery URL when OAuth methods are supported
gnap_grant_endpointstringNoGNAP grant endpoint when GNAP is supported
supported_profilesstring[]NoDomain extension profiles this Exchange conforms to (e.g., ["ramp-academic-v1", "ramp-news-v1"])
base_currencystringNoISO 4217 currency code for all unit_cost values in offers (e.g., "USD")
contactstringNoContact email for integration inquiries
terms_uristringNoTerms of service URL
privacy_uristringNoPrivacy policy URL
extobjectNoExtension fields (forward-compatible)

RAMP defines one well-known file. Every participant serves a WellKnownManifest at /.well-known/ramp.json; the role field says which participant it is.

RoleServed ByPurpose
ROLE_PUBLISHERProviderWho is authorized to sell my content; my signing keys
ROLE_EXCHANGEExchangeMy endpoints, capabilities, accepted verifiers, and offer-signing keys
ROLE_AGENTAgent / BrokerMy Ed25519 public key for request signing

A verification vendor has no dedicated role — it publishes under its operator’s role (ROLE_PUBLISHER when self-attesting, ROLE_EXCHANGE for a standalone vendor); its keys go in public_keys and its claims schema in ext["ramp.attestation.claims_schema"].

The manifests form a discovery chain that a Broker follows:

1. Agent requests content from provider.example.com
2. Fetch provider.example.com/.well-known/ramp.json
--> role=ROLE_PUBLISHER; discovers authorized Exchange + provider keys
3. Fetch exchange.example.com/.well-known/ramp.json
--> role=ROLE_EXCHANGE; discovers endpoints, capabilities, and inline
public_keys for offer signature verification (no separate keys fetch)
4. (If attestation required) Fetch doubleverify.com/.well-known/ramp.json
--> verifier's public_keys for attestation signature verification

Each step narrows the information needed: a publisher manifest tells you WHERE to go, and an exchange manifest tells you WHAT the Exchange can do and HOW to verify its signatures (keys are inline).

The Broker uses the manifest to filter Exchanges before sending any RPCs. This avoids querying Exchanges that cannot fulfill the agent’s requirements.

QuestionManifest Field
Does this Exchange support per-unit (metered) pricing?pricing_models_supported
Can this Exchange deliver via signed URL?delivery_methods_supported
Does this Exchange trust DoubleVerify?accepted_verifiers
Does this Exchange speak protocol v1.0?protocol_versions_supported
Where do I verify offer signatures?public_keys (inline JWKs)

Without the manifest, the Broker discovers these answers only after sending requests and observing responses — wasting latency and bandwidth on Exchanges that will reject the request.

1. Agent requests URI for domain "provider.example.com"
2. Broker fetches provider's ramp.json --> finds authorized Exchange
3. Broker fetches exchange's ramp.json (role=ROLE_EXCHANGE) --> capabilities + inline keys
4. Broker caches manifest with 1-hour TTL (emergency revocation via invalidation_url)
5. Broker registers Exchange in its registry with capabilities populated
6. Subsequent requests skip steps 2-4 (cache hit)

The Exchange manifest is a WellKnownManifest with role=ROLE_EXCHANGE, defined in ramp.proto. Keys are inline public_keys (no separate keys_uri fetch). Exchange-relevant fields:

message WellKnownManifest {
string ver = 1; // "1.0"
Role role = 2; // ROLE_EXCHANGE here
string domain = 3;
optional string contact = 4;
repeated JsonWebKey public_keys = 5; // inline Ed25519 offer-signing keys
optional string invalidation_url = 6; // emergency revocation list
optional string name = 9;
optional string operator = 10;
optional string operator_domain = 11;
optional string endpoint = 12; // ExchangeService URL
optional string health_endpoint = 13;
optional string catalog_endpoint = 14;
repeated string protocol_versions_supported = 16;
repeated PricingModel pricing_models_supported = 17;
repeated DeliveryMethod delivery_methods_supported = 18;
repeated string hash_methods_supported = 19;
repeated string accepted_verifiers = 20;
repeated string supported_profiles = 23;
repeated AuthMethod supported_auth_methods = 24;
optional string oidc_issuer = 25;
optional string gnap_grant_endpoint = 26;
optional string base_currency = 27;
google.protobuf.Struct ext = 15;
// ... publisher-only fields (exchanges, catalog_contributors) omitted ...
}

The JSON endpoint serves the same data as this proto message, but as plain JSON (not protobuf wire format). It is a discovery document, not an RPC response.