carousell/rctp

Re-Commerce Trust Profile (RCTP) — Draft 0.5

Editor's draft, 10 November 2026: the implementation baseline

This version spec/rctp-draft-0.5.md
Previous version Draft 0.4, 27 October 2026
Implementation carousell/rctp: v0.3.0-draft.5 implements the Starter profile of this draft (wire binding); v0.2.0-draft.4 implemented Draft 0.4
Editor Kelvin Vuong
Feedback GitHub issues with the label draft-0.5
Changes Appendix C: decisions and changes

Abstract

RCTP is a profile of existing commerce standards that lets AI agents buy and sell second-hand goods for people. A person delegates the whole trade to their agent, with their consent. Every seller and every unique item has a profile both sides can check. The marketplace's gateway enforces the seller's limits on every call and keeps a signed record. RCTP reuses the Universal Commerce Protocol (UCP) and the Agent Payments Protocol (AP2) wherever they already define a verb or noun, and defines only five things of its own: offers, Listing Terms, the enforcement decision, signed proof of who did what, and portable credentials about people and items.

Status of this document

This is the editor's draft of 10 November 2026. It incorporates the Draft 0.5 proposal (#91), which the editor accepted as the implementation baseline on that day: new implementations build on this draft, not on Draft 0.4. Lazy consensus under GOVERNANCE runs until 17 November 2026; anything it changes is applied here before release v0.3.0-draft.5 is tagged. It is still a draft, not a standard: names, fields and numbers may change in a later draft.

It supersedes Draft 0.4. Draft 0.5 changes no mechanism that protects a trade. It removes rules that were stricter than UCP (authentication, 4.1), moves tier policy to the marketplace (8.4), and lets a seller state Listing Terms in plain language (6). The open questions raised for this draft and their resolutions are in Appendix B. Every decision since Draft 0.3, and the history of earlier drafts, is in Appendix C.

Placeholder domains use .example. Capability and extension names use dev.rctp.*, backed by the domain rctp.dev, which the project controls.

1. Introduction

1.1 Scope

RCTP covers person-to-person trade in used goods where one or both sides act through an AI agent. It defines how a seller authorises an agent, how the seller's limits are set and enforced, how agents negotiate, how each step of a deal is proven, and how facts about people and items travel between platforms.

Out of scope: booking, quoting and tracking shipments; moving money; negotiation strategy and pricing; identity-proofing methods; transports. RCTP composes with the standards that cover them (1.4).

1.2 What RCTP gives each party

Delegated by consent A person hands their agent the whole trade, with their consent: what it may do, under which limits and until when (5). They can revoke it at any time (5.4).
Transparent profiles Every seller and every unique item has a profile both sides can check: the seller's track record in bands (Party Credential, 11.1), and the item's passport and history (Item Passport, 11.3).
Guardrails, enforced The marketplace's gateway, and every party in the ecosystem, enforces the seller's limits on every call (8) and keeps a signed record of what happened (10).

The profile defines verbs, scopes and invariants, and records facts. Marketplaces and platforms set policy: which authentication mechanisms they accept (4.1) and which tiers they allow (8.4).

1.3 Design principles

Simplicity is the ultimate complexity. RCTP defines the minimum a marketplace must implement and operate. Categories and logistics chains extend it through open values, not new protocol. Where UCP or AP2 defines a verb or noun, RCTP uses it.

Six rules are fixed. Everything else is an open value named by reverse domain, as in UCP.

ID Fixed rule
FR-1 The platform enforces the seller's terms, not the agent.
FR-2 No answer means no.
FR-3 The marketplace never discloses private terms to any agent.
FR-4 Money moves only on signed proof.
FR-5 Facts about people, never identities.
FR-6 No custom cryptography.

1.4 Relationship to UCP and AP2

Pinned to UCP release v2026-08-25 and AP2 v0.2. UCP Ask is not yet in a UCP release; RCTP follows it at UCP commit f2626c2 (20 October 2026) until it is.

Need Defined by RCTP adds
Agent identity and authentication UCP: UCP-Agent, profiles at /.well-known/ucp, identity binding; RFC 9421 signatures (recommended), OAuth 2.0, API keys or mTLS Accountability fields in the profile; how each call authenticated, in the record (4.1)
Seller's permission for an agent UCP Identity Linking: OAuth 2.0 at the marketplace, scopes {capability}:{scope} RCTP scopes, tiers, key binding (5)
Buyer questions UCP Ask Answers from structured facts only (8.3)
Delivery method, carrier, windows, cost UCP Fulfillment (open method types) Nothing
When payment is due UCP Payment Terms Nothing
Paying into escrow AP2 Payment Mandate: payment.allowed_payees Nothing
Checkout, order, shipping and money events UCP Checkout and Order: fulfillment events and adjustments Who attests each event (10)
Webhooks UCP signed webhooks (Standard Webhooks headers, RFC 9421) Nothing
Transports UCP REST and MCP bindings RCTP verbs as REST routes and MCP tools (12)
Price negotiation Not defined; UCP discussion #502 is open dev.rctp.deal (7)
Seller limits, enforcement, signed proof, people and item facts Not defined Sections 6, 8, 10, 11

1.5 Conventions

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY and OPTIONAL are to be read as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals. Numbered rules are normative; tables define fields and values; examples and notes are informative. Values in code are registered (16) unless marked as examples.

2. Terminology

Term Meaning
Agent Grant The seller's permission for one agent to act for them on one marketplace (5)
Listing Terms The seller's limits for one listing, confirmed by the seller and enforced by the platform (6)
Proposed terms Terms values a seller agent carries from what the seller told it; nothing until the seller confirms them (6.1)
Floor The lowest price the seller accepts; interfaces may call it the "lowest price" (6.2)
Term set The terms a category takes, their types and limits (6.2)
Deal A trade a buyer and a seller agree through offers, from the first offer to the release of funds (7, 10)
Deal Terms What an offer proposes and an acceptance fixes: price, fulfillment option, payment term (7.2)
Negotiation The offers and counters between one buyer agent and one listing, linked by negotiation_id (7.2)
Reservation The hold an accepted offer places on its listing until its checkout is redeemed or expires (7.4)
Enforcement point The marketplace gateway that decides every agent call (8)
Tier auto (act), ask (act only after the seller approves) or forbid (never act)
Authentication mechanism How a call authenticated: http_signature, oauth, api_key or mtls (4.1)
Holder of funds The party that holds the buyer's payment: the AP2 payee, either the marketplace or a licensed payment partner
Carrier, Custodian A party that moves or holds an item, and signs what it observed
Attester A party that signs facts about one item, such as a registry, inspector or notary
Issuer A party that signs portable credentials, usually a marketplace
Identity issuer A public e-ID service or licensed eKYC provider that signs identity facts (11.2)
First-hand, relayed Whether the signer observed the event, or passes on a named partner's report
Deal record The hash-chained, signed entries for one deal (10)
Trusted Surface A screen the person controls where consent and approvals are given, as in AP2
Band A coarse range that replaces a raw number, such as 50-200 trades
Pairwise pseudonym An identifier unique to one relationship or one deal
Verified custody lane A deal in which a Custodian checks the item and payment is released when the buyer accepts it (11.4)

3. Roles

RCTP names roles, never companies. One organisation MAY play several roles; each role's duties apply in full.

Role MUST MUST NOT
Marketplace Issue Agent Grants; hold Listing Terms; run the enforcement point; write the deal record Disclose private terms to any agent; store a grant or terms the seller did not confirm
Seller agent Act within its grant; answer from structured facts; propose only terms the seller stated Act outside its granted verbs
Buyer agent Act within the buyer's AP2 mandates; default to protected payment (8.6) Pay off-platform or pass payment links without an explicit ask
Holder of funds Sign funds_held, released and refunds; release only on the deal's release condition Release before the condition holds
Carrier, Custodian Sign only what it observed; publish liability terms Attest outside its observation
Issuer, Identity issuer, Attester Sign only what it verified; publish methodology and status lists Learn which verifier checked which credential
Approval surface Show the exact action and amount; return the seller's own signature (9) Approve on timeout; sign with an operator key

4. Common rules

4.1 Agent identity and authentication

  1. Every agent request to an enforcement point MUST authenticate by a mechanism UCP allows: HTTP Message Signatures per UCP Message Signatures (RFC 9421, ES256 baseline), which are RECOMMENDED; an OAuth 2.0 access token; an API key; or mTLS. The marketplace chooses which mechanisms it accepts. The request carries UCP-Agent naming the operator's UCP profile; a signed request MUST. When a call authenticated by OAuth carries no UCP-Agent, the enforcement point MAY use the profile it registered for the OAuth client; when it carries one, the two MUST match. Either way, the enforcement point MUST confirm that the authenticated principal may act for that profile (UCP identity binding).
  2. The operator's profile MUST publish its signing keys in keys[] when its agents sign, and MUST add a dev.rctp.operator entry with legal_entity, jurisdiction, incident_contact and incident_sla_hours. It MAY add certifications, data_residency and key_custody.
  3. An enforcement point MUST refuse a call whose profile cannot be resolved, whose operator it has not onboarded, or whose UCP-Agent does not match the profile registered for its authenticated client, with operator_unknown.
  4. An operator whose agents act for sellers MUST NOT export buyer data, contact buyers outside the marketplace, or use RCTP data for advertising.
  5. An agent without a UCP profile of its own, such as a plugin on an agent host, uses the profile its developer publishes as operator. A marketplace MAY instead host a profile for each OAuth client it registers. Either way, the profile names an operator accountable under rule 2. An operator without a profile of its own accepts the duties of rules 2 and 4 in its OAuth client registration with the marketplace. The agent host that runs a plugin, such as its model provider or IDE, sees the conversation, buyer data included, and is not bound by rule 4. That is the real difference from an operator whose agents sign; a marketplace weighs it when it sets tiers for OAuth clients (8.4).
  6. Every deal record entry the enforcement point writes for an agent call, decisions and refusals included, MUST carry authenticated_by, the mechanism the call used, and agent_profile, the profile the call acted for (10.1). An entry for an OAuth or API-key call MUST also carry client_id, the client that authenticated. Whether a token was key-bound follows from the mechanism (5.3).
  7. What each mechanism may do is the marketplace's policy (8.4). Without a signature, the record proves which client acted for which profile, not the content of each request; a marketplace weighs that when it sets tiers. The controls for bearer tokens are short-lived access tokens, refresh-token rotation and the live grant check on every call (5.3(2)). DPoP (RFC 9449) is a possible middle step for clients that can hold a key but cannot sign every request; it waits for a pinned library (INV-8).

4.2 Portable credentials

  1. Party Credentials, identity facts, Item Passport attestations and deal records are SD-JWT VCs (RFC 9901, draft-ietf-oauth-sd-jwt-vc) with typ dc+sd-jwt, carrying vct, iss, iat, exp, cnf and status.
  2. Every credential MUST be bound to a holder key through cnf. A presentation MUST include a key-binding JWT whose aud is the verifier and whose nonce the verifier supplied.
  3. Holder keys SHOULD be hardware-backed and not exportable.

4.3 Status lists

  1. Credential revocation MUST use the Token Status List. Each list MUST be shared by many credentials; a list per holder or per credential is forbidden.
  2. Verifiers SHOULD fetch whole lists and cache them for their stated lifetime.
  3. Agent Grants do not use status lists; they are checked live (5.4).

4.4 Bands

Numeric facts about people MUST be expressed as registered bands, never raw numbers.

4.5 Names, versions and open values

  1. Capability names use dev.rctp.<name>. Credential types end in a version number; a breaking change increments it.
  2. Method types, event types, adjustment types, attestation types and term names are open values. A party MAY add a value under its own reverse domain; parties that do not recognise it MUST treat it as informative and MUST NOT let it change a decision.
  3. The capability version of this draft is 2026-11-draft5. A deployment MAY keep serving 2026-11-draft4 beside it for at most 90 days after it starts serving 2026-11-draft5.

5. Agent Grant

An Agent Grant is a UCP Identity Linking grant, issued by the marketplace, with RCTP scopes. It is bound to one agent key when the agent signs (5.3). It carries no prices and no listings.

5.1 Grant record

Field Content
grant_id grt_ followed by a unique identifier
seller Pairwise pseudonym of the seller for this marketplace and operator
operator, agent_id The operator's UCP profile URL and agent identifier
cnf.jkt RFC 7638 thumbprint of the bound agent key, when the grant is key-bound (5.3)
scopes Granted RCTP scopes (8.4)
tiers The seller's per-scope tier, within the tiers the marketplace allows for each scope (8.4)
consent Consent screen version, time and account assurance; kept by the marketplace
iat, exp, status Issue and expiry times; active, revoked or expired

5.2 Issuance

  1. The marketplace MUST issue a grant through UCP Identity Linking (OAuth 2.0 authorization code with PKCE) only after the seller confirms, on a Trusted Surface, the agent, its operator, each verb with its tier, and the expiry.

  2. The marketplace's profile declares each RCTP scope (8.4), as UCP declares every scope, in the config.scopes of its dev.ucp.common.identity_linking entry, with default_tier and allowed_tiers in the scope's policy. The seller's chosen tiers travel as RFC 9396 authorization details of type dev.rctp.agent_grant.

  3. The consent screen MUST NOT ask for prices. Prices belong to Listing Terms.

  4. A grant MUST expire at most 90 days after it is issued; the agent renews it by refresh-token rotation. A marketplace MAY expire a grant earlier when it is unused.

5.3 Use on every call

  1. The agent sends the grant's access token in Authorization. When the request is signed, the token MUST be sender-constrained with cnf.jkt (RFC 7800), and the request signature MUST cover authorization. When it is not signed, the token is the request's OAuth credential.
  2. The enforcement point MUST look the grant up on every call, whatever the authentication mechanism and bearer tokens included, and check that the grant is active and unexpired and that the verb's scope is granted. When the token is bound, it MUST also check that the signing key's thumbprint equals cnf.jkt.

5.4 Revocation

  1. The seller can revoke a grant at any time; operators can revoke their own tokens (RFC 7009).
  2. A revoked or expired grant MUST fail the next call, whatever its authentication mechanism.

6. Listing Terms

Listing Terms are the seller's negotiating envelope for one listing. The seller states them to their agent in plain language, such as "list it at 500, don't go below 400", and confirms them once on a Trusted Surface. The platform stores what the seller confirmed and enforces it on every call. Everything between the floor and the list price is the agents' to negotiate; the marketplace never sells below the floor, whatever anyone says to an agent.

6.1 Setting terms

  1. The seller agent calls listing.create with the item and its public list price. It MAY include proposed terms: the values the seller told it, the floor included.
  2. Terms are confirmed on a Trusted Surface (the marketplace's hosted page or app). It shows the listing and a form built from the category's term set, pre-filled with the proposed terms and the marketplace's category defaults (6.2), all editable. The seller confirms with their passkey. This is the expected flow. A marketplace MAY ignore proposed terms and ask the seller for the floor directly; that is its policy.
  3. The approval challenge MUST bind the listing hash and the terms_commitment (6.4). The platform MUST store exactly the terms the seller confirmed. Proposed terms are not terms: the enforcement point MUST NOT store or enforce them until the seller confirms them, and MUST discard them if the seller declines.
  4. The seller agent learns the outcome, the term set ID and terms_commitment. The marketplace MUST NOT return the private values to any agent, including the seller agent that proposed them.
  5. When the marketplace allows listing.create at auto (8.4), the listing is created without terms, and stays closed to agent negotiation until the seller confirms terms through listing.set_terms (6.5).
  6. A listing a seller creates by hand in the marketplace app takes the same form.

6.2 Term sets

A term set, such as goods.small/1, defines the terms a category takes. A listing records the term set version it was approved under. Platforms MUST advertise the term sets they enforce in the config of dev.rctp.listing in their UCP profile.

  1. The minimum Listing Terms are two prices: the public list price, already on the listing, and the private floor. Every term set MUST include floor and available_until; every other term is optional.
  2. required in a term set means the term has a value when the seller confirms, not that the seller types it. The marketplace fills each public term from its category defaults, available_until included, and the seller changes them only if they want to.
Term Type Visibility Enforced at
floor money private offer.create, offer.counter, offer.accept, listing.reprice
available_until date-time public Every offer; after it the listing is closed
fulfillment_options UCP fulfillment method types and options public offer.create (7.2)
payment_terms UCP payment terms public offer.create (7.2)
release_condition buyer_accepted, handover_inspection_passed public The holder of funds (10.3)
deliver_within_days integer public Refunds (10.3)
counterparty_requirements minimum bands and identity assurance public offer.create
deposit_pct, inspection_before_deposit percent, boolean public deal.accept_deposit
required_observation first_hand or relayed, per checkpoint public Release and refund (10.3)

Constraints come from a closed set, so every platform checks them the same way: min, max, gt_term, lt_term, lte_list_price, min_ratio_of_list_price. Terms that break a constraint MUST be refused with terms_invalid before the seller can approve them. Which terms a term set includes is the marketplace's choice for that category.

6.3 Changing terms

  1. listing.set_terms changes terms. It has no tier choice: it always opens the seller's confirmation and is answered ask (8.4). It MAY carry proposed terms, which are handled as in 6.1.
  2. listing.reprice changes the public price; a price below the floor MUST be refused with below_floor.
  3. Open offers are re-evaluated against new terms the next time a party acts on them. Accepted offers are not (7.4).

6.4 Keeping private terms private

  1. Private terms, proposed or confirmed, MUST NOT appear in listing data, offers, decisions, approval request bodies, webhooks, partner-readable logs, deal records or any other response to an agent. They appear only on the seller's Trusted Surface.
  2. Deal records carry terms_commitment: SHA-256 over the RFC 8785 canonical JSON of {salt, terms}, with a 128-bit salt kept by the platform.
  3. The platform discloses private terms only to the seller, and to an arbiter in a dispute the seller is party to. No setting lets the marketplace send them to an agent.
  4. A seller may tell their own agent the floor; that is the seller's choice, and it is how proposed terms work (6.1). An agent that knows the floor can still be talked into revealing it. The guarantee does not depend on the agent: no sale happens below the floor (8). A marketplace that wants the floor kept from every agent asks the seller for it directly (6.1(2)).

6.5 Listings without terms

A listing with no approved terms is not open to agent negotiation. Offers on it reach the seller as ordinary marketplace offers; a seller agent acting on it is refused not_in_scope.

7. Offers and Deal Terms

7.1 Offer capability

RCTP defines two UCP capabilities. Both are standalone, not extensions of dev.ucp.shopping.checkout.

Capability Covers Profile config
dev.rctp.listing Listings and their Listing Terms (6) Term sets enforced (6.2)
dev.rctp.deal A negotiated trade between a buyer and a seller: offers, acceptance and the checkout it produces, and the deal record (7, 10) Offer expiry default and maximum (7.3); offer budget (8.5)

A deal is a trade both parties agree to, not a promotion or a discount. An offer is its own resource, formed before any checkout exists; accepting one produces a UCP checkout (7.4). Payment, shipping and order events stay with UCP Checkout and Order; dev.rctp.deal adds who attests them (10). Offer operations: create, counter, accept, decline, get. An RCTP offer is not UCP's Offer extension, which is a merchant-proposed change to a cart.

7.2 Deal Terms

  1. An offer carries Deal Terms: a price, one UCP fulfillment option and one UCP payment term, each chosen from those the listing's terms allow.
  2. A choice the listing does not allow MUST be refused with terms_invalid.
  3. Booking, quotes, labels and tracking stay with UCP Fulfillment and the carrier.
  4. Every offer and counter carries offer_id, negotiation_id and expires_at (7.3). The enforcement point assigns negotiation_id to a buyer agent's first offer on a listing; every later offer and counter between that buyer agent and that listing carries the same value. It is opaque and MUST NOT be derived from any identifier of the buyer.
  5. An offer that answers a counter, or replaces the buyer agent's own open offer, MUST name it in supersedes. The enforcement point sets the named offer to superseded. A supersedes that names an offer outside the negotiation MUST be refused with terms_invalid.

7.3 Offer states and who accepts

States: open → countered or awaiting_approval → accepted, declined, expired, superseded or refused. An offer is awaiting_approval while an ask on it waits for the seller.

  1. Only the seller side accepts, under offer.accept. A counter is an invitation, not a commitment; a buyer agrees to it by offer.create at the counter's Deal Terms.
  2. The party that creates an offer or counter sets its expires_at; if it is omitted, the enforcement point sets the default it publishes in the config of dev.rctp.deal. The enforcement point MUST cap expires_at at the listing's available_until and at the maximum it publishes.
  3. At expires_at an offer that is not accepted becomes expired; acting on it MUST be refused with offer_expired.
  4. An ask raised on an offer expires no later than the offer. When it times out, the offer becomes expired.
  5. Seller counter-offers are the marketplace's option. A marketplace that does not support them leaves dev.rctp.deal:offer_counter out of its config.scopes, and agents learn that from discovery. Floor defence alone is complete: an offer below the floor is refused; at or above it, the offer goes to the seller or their agent to accept or decline.

7.4 Acceptance, reservation and checkout binding

  1. An accepted offer MUST become a business-signed checkout bound to the listing hash, offer ID, Deal Terms, buyer agent key thumbprint, expiry and a single-use nonce. A second use MUST fail with offer_replayed.
  2. Accepting an offer reserves the listing for that checkout. While the reservation holds, the enforcement point MUST refuse every other offer.accept on the listing with listing_reserved, and MUST NOT create a second checkout for it. Buyer agents MAY still make offers; they stay open until they expire.
  3. The reservation ends when the checkout is redeemed, which closes the listing, or when the checkout expires, which reopens the listing to offers that have not expired.
  4. Once an offer is accepted, its Deal Terms are fixed. A later listing.set_terms or listing.reprice MUST NOT change them or end the checkout.
  5. Only the seller, on a Trusted Surface, can withdraw a reserved listing. Redeeming its checkout then fails with not_in_scope, and the withdrawal is written to the deal record.

7.5 Buyer authority and payment

  1. An enforcement point MUST accept a valid AP2 Checkout Mandate as proof that a buyer agent may offer, and MUST refuse an offer outside its constraints with buyer_authority_exceeded.
  2. The buyer's AP2 Payment Mandate SHOULD constrain the payee with payment.allowed_payees to the deal's holder of funds.
  3. Agents MUST NOT pass payment links or payment instructions between the parties.

8. Enforcement decisions

The enforcement point, not the agent, decides every action.

8.1 Check order

Step Check Refusal
1 Authentication and operator 401 signature_invalid, grant_invalid, operator_unknown
2 Grant: known, active, scope granted; key-bound when signed (seller side) 401 grant_invalid; 403 grant_revoked, grant_expired, action_forbidden
3 Listing: the grant's seller's, has terms, open; for offer.accept, not reserved; offer not expired 403 not_in_scope; 409 listing_reserved, offer_expired
4 Buyer authority and counterparty_requirements (buyer side) 403 buyer_authority_exceeded, counterparty_requirements_unmet
5 Terms: floor, Deal Terms, offer budget 403 below_floor, 422 terms_invalid; 429 offer_budget_exhausted
6 Tier: the grant's tier or the marketplace's default 200 auto; 202 ask

An unauthenticated request is refused at step 1: signature_invalid where the marketplace requires signatures, otherwise grant_invalid for a seller verb and operator_unknown for a buyer verb. Every decision, including each refusal, appends a deal record entry (10) carrying authenticated_by and agent_profile (4.1(6)).

8.2 Decision header

The decision travels in an RFC 9651 Structured Field: a Token (auto, ask, forbid) with parameters.

Decision HTTP Parameters
auto 200, 201 none
ask 202 approval_id, expires_in, on_timeout=deny; the body carries the approval request (9)
forbid 401, 403, 409, 422 action, reason
forbid 429 reason=offer_budget_exhausted, retry_after
  1. A refusal for a low offer MUST use below_floor and carries no private term: it MUST NOT state the floor or any value derived from it. An agent that wants a reference price reads the public list price on the listing.

  2. No agent input, prompt or listing text can change a tier, a term or a grant.

  3. The header is named RCTP-Decision.

8.3 Decisions by verb

Verb By Below the floor Otherwise
offer.create Buyer agent 403 below_floor; counts against the budget 201, delivered to the seller agent
offer.counter Seller agent, where offered (7.3(5)) 403 below_floor Tier
offer.counter Buyer agent Treated as offer.create at the counter amount
offer.accept Seller agent 403 below_floor Tier
offer.accept Buyer agent 403 action_forbidden
listing.reprice Seller agent 403 below_floor Tier
listing.answer_buyer Seller agent Tier; answered through UCP Ask from structured listing and passport facts only

8.4 Verbs, tiers and scopes

Every seller verb belongs to one of RCTP's two capabilities (7.1), and its scope is {capability}:{scope} as in UCP Identity Linking. A verb's prefix names its capability: listing.x is dev.rctp.listing:x, deal.x is dev.rctp.deal:x, and offer.x is dev.rctp.deal:offer_x. Fixed forbid verbs have no scope, so no grant can contain them.

  1. The Default and Allowed columns are reference defaults, like the reference offer budget (8.5). A marketplace declares its own default_tier and allowed_tiers for each scope it offers, in the config.scopes of its dev.ucp.common.identity_linking entry (5.2). It MAY vary them by authentication mechanism (4.1). It leaves out a scope it does not offer.
  2. The seller chooses a tier within what the marketplace allows, at consent and later.
  3. Three things are fixed, because they are mechanics, not policy: listing.set_terms always opens the seller's confirmation (ask); only the seller confirms terms (INV-5), so a listing created at auto has no terms until the seller confirms them (6.1(5)); and deal.sign_contract and account.update are always forbid (INV-3).
Verb Scope Default Allowed Notes
listing.create dev.rctp.listing:create ask ask, auto At auto, created without terms until the seller confirms them
listing.set_terms dev.rctp.listing:set_terms ask ask Fixed: always opens the seller's confirmation
listing.reprice dev.rctp.listing:reprice auto auto, ask Never below the floor
listing.answer_buyer dev.rctp.listing:answer_buyer auto auto, ask
offer.counter dev.rctp.deal:offer_counter auto auto, ask Never below the floor; optional for a marketplace (7.3(5))
offer.accept dev.rctp.deal:offer_accept ask ask, auto Never below the floor
deal.commit_to_ship dev.rctp.deal:commit_to_ship ask ask, auto
deal.disclose_passport dev.rctp.deal:disclose_passport ask ask, auto Discloses the full Item Passport report (11.3)
deal.accept_deposit dev.rctp.deal:accept_deposit ask ask
deal.sign_contract none forbid forbid Fixed
account.update none forbid forbid Fixed

offer.create is a buyer verb: it is checked against the terms and has no tier. Buyer verbs need nothing RCTP-specific beyond authentication (4.1): checkout and payment authority come from UCP and AP2, or another payment protocol, which carry their own proof.

8.5 Offer budget

  1. The enforcement point MUST count below-floor offers per buyer agent per listing, with a ceiling per buyer operator per listing. It publishes both numbers in the config of dev.rctp.deal.
  2. Past either limit, every offer from that agent or operator on that listing gets 429 until the window frees a slot, so 201-versus-429 cannot reveal the floor.

8.6 Buyer agent defaults

  1. A buyer agent MUST, by default, pay for second-hand goods only into protected payment: the verified custody lane, or a holder of funds with a release condition.
  2. A buyer agent MUST NOT pay a counterparty directly, or move a conversation to an outside channel, when a protected path exists, unless its principal approves an explicit ask stating the purchase is unprotected.
  3. Before payment, a buyer agent MUST tell its principal which item facts are attested and by whom.
  4. An enforcement point MUST NOT refuse a buyer only for insufficient-history or zero trades when the deal uses the verified custody lane.
  5. A principal MAY change these defaults only on a Trusted Surface.

9. Approvals

A partner's app can show an approval, but only a key the seller controls can sign it.

9.1 Levels

Level Shown in Signed with Allowed when
marketplace_app The marketplace's app The seller's marketplace passkey Any amount
hosted_embedded A marketplace-hosted panel opened in the partner's app The seller's marketplace passkey Any amount; recommended for partners
certified_operator The partner's own interface A hardware-backed approval key on the seller's device Certified operators only, below the grant's cap

9.2 Request and response

  1. The request travels in the 202 body: approval_id, action, listing hash, amount, counterparty bands, display, expires_at, a one-time challenge and the allowed levels. The challenge is SHA-256 over the RFC 8785 canonical JSON of RFC 9396 authorization details of type dev.rctp.approval.
  2. display MUST NOT contain private terms. A listing approval shows the terms form, pre-filled as in 6.1, on the seller's Trusted Surface only, and its challenge binds terms_commitment.
  3. The response carries approval_id, decision, the signature over the challenge (a WebAuthn assertion at the first two levels), the level, and the SHA-256 of the text shown.

9.3 Rules

  1. Before acting, the enforcement point MUST verify that the signature is the seller's registered key, answers this challenge, is within expires_at, is first used, and uses an allowed level; otherwise approval_invalid or approval_surface_not_allowed.
  2. No reply by expires_at is a decline. A late response is refused approval_invalid; the approval is reported expired with approval_timeout.
  3. Any amount above the certified cap MUST use marketplace_app or hosted_embedded.
  4. The approval, its level and the displayed-text digest are written to the deal record.
  5. The seller's approval key is their existing marketplace account passkey; how it is registered is the marketplace's concern.

10. Deal record and proof

A deal record (vct = attestation.transaction.1) is the hash-chained list of signed entries for one deal. UCP Order events say what happened; the deal record says who attests it, and which proofs move money.

10.1 Entries

Field Content
deal_id, seq, prev_hash Deal, position, and SHA-256 of the previous entry
t, author Time; pairwise pseudonym of the signer, or the enforcement point's identifier
authenticated_by, agent_profile, client_id For agent calls: the authentication mechanism, the profile the call acted for and, for OAuth and API-key calls, the client (4.1(6))
action, tier, result For decisions: the verb, tier and outcome
event A RCTP checkpoint (10.2) or a UCP fulfillment event or adjustment type, such as shipped or refund
observation first_hand or relayed; relayed entries add reported_by and source_event_id
evidence Digests of photos, codes, seal references or documents
approval, terms_commitment, ucp_order_ref, ap2_refs Approval details; the terms commitment; the UCP order; digests of AP2 mandates and receipts
countersignatures Optional signatures of other parties

10.2 Events and who attests them

RCTP defines only the checkpoints UCP lacks. Shipping, delivery and money adjustments use UCP's open types.

Event Defined by Signed by
funds_held RCTP Holder of funds
shipped, delivered, returned_to_sender UCP fulfillment event Carrier (first_hand), or the marketplace (relayed)
accepted, rejected (reason: not_as_described, not_received) RCTP Buyer agent
return (completed) UCP adjustment Seller, carrier or Custodian
released RCTP Holder of funds
refund UCP adjustment Holder of funds

Category events, such as picked_up_sealed or custody_inspected (11.4), are open values added by term sets.

10.3 Money rules

  1. released requires funds_held, then the deal's release condition (by default accepted).
  2. After rejected with not_as_described, refund requires an attested, completed return.
  3. rejected with not_received is allowed only after deliver_within_days since funds_held; a refund then needs no return.
  4. Where a term set sets required_observation, the named events count only when signed with that observation.
  5. Any other order fails with 409 release_condition_unmet.

10.4 Rules

  1. The enforcement point MUST write an entry for every decision, including refusals, and MUST NOT record a floor.
  2. A relayed entry asserts that a named partner reported the event, not that it happened; partner terms carry the liability.
  3. A refusal to countersign MUST NOT invalidate an entry.
  4. Either party MAY submit the record to an arbiter in a dispute, for that case only. A holder MAY submit it to its own issuer to update its bands.
  5. Entries MUST NOT contain addresses, phone numbers or names. Locations are city-level; evidence is referenced by digest.

11. Portable credentials

Facts that should travel between platforms are SD-JWT VCs (4.2), presented by the holder's agent directly. The issuer is never contacted per presentation.

11.1 Party Credential

vct = credential.counterparty.1 states what kind of trader a person is, as a seller and as a buyer, without saying who they are.

Claim Section Values
identity_assurance Common Level (phone_only, document_check, bank_kyc, gov_eid), source, observation
account_tenure_band Common lt-6m, 6-24m, 24-48m, 48m-plus
kyc_standing Common verified-current, verified-expired, unverified
markets_recognised Common ISO 3166-1 alpha-2 codes
seller.completed_sales_band Seller 0, 1-9, 10-49, 50-200, 200-plus
seller.dispute_rate_band Seller lt-1pct, 1-3pct, 3-10pct, 10pct-plus, insufficient-history
seller.dispute_resolution_outcome Seller no-adverse-finding, adverse-finding-resolved, adverse-finding-open
buyer.completed_purchases_band Buyer 0, 1-9, 10-49, 50-200, 200-plus
buyer.adverse_findings_band Buyer 0, 1, 2-plus, insufficient-history
buyer.no_show_band Buyer lt-5pct, 5-20pct, 20pct-plus, insufficient-history
  1. No sub or stable holder identifier. Issuers SHOULD issue in batches with fresh keys; agents SHOULD use each credential once.
  2. Dispute and buyer bands MUST read insufficient-history below a published minimum.
  3. The band methodology MUST be published, MUST exclude trades between linked accounts, and MUST be reviewed by an independent party yearly.
  4. Holders MUST be able to view and contest their bands and inputs.
  5. Buyer bands count only events the issuer was party to; complaints count only once upheld through a process the buyer could answer.
  6. A verifier MUST request only the claims it needs and only the section that fits the holder's role, and MUST check signature, key binding, type and status locally.

11.2 Identity facts

vct = credential.identity.1 carries facts a public e-ID service or licensed eKYC provider verified.

Claim Values
verified_person true
age_over_18 true or false
residency_country ISO 3166-1 alpha-2 code
registered_business true, with a salted digest of the registration
licensed_trade Licence type and issuing authority
assurance Level, source service, and first_hand or relayed
  1. Names, identity numbers, dates of birth and addresses MUST NOT appear.
  2. An identity issuer MUST sign only facts it verified, never reputation or trade history.
  3. A marketplace that re-signs facts a public e-ID service confirmed MUST mark them relayed with source and time, keep the source response for audit, and never forward it.
  4. Accepted identity issuer keys are published per country in an open trust list.

Illustrative sources, subject to each service's terms: Singpass Myinfo, VNeID, MyDigital ID, iAM Smart.

11.3 Item Passport

Each attestation (vct = passport.item.1) is signed by the attester that checked the fact.

Claim Content
item_ref Salted digest of the item identifier (VIN, IMEI, title number)
attestation_type A registered or extension type
result, details The finding; selectively disclosable specifics
observed_at, valid_until When checked; until when the attester stands behind it
disclose_at listing, reserve or deposit
liability_terms URL of the attester's liability terms

Registered types: registration_match, periodic_inspection, lien_free, inspection_report, title_verified, ownership_or_poa, owner_match, planning_zone, grade_certificate, custody_verified, handover_inspection, return_match, authenticity_check, device_clean.

  1. Listing and passport facts MUST be structured; seller agents MUST answer from them, not from free text.
  2. Attesters MUST be able to revoke an attestation through their status list.
  3. An authenticity_check MUST state its method (human, lab, model) and examiner or model version. A model result alone MUST read screening_pass, screening_fail or inconclusive, never authentic, unless liability terms cover a wrong call.

11.4 Verified custody

  1. A Custodian MUST inspect the item at a checkpoint or at pickup, and sign custody_verified bound to the listing hash, item_ref and photo digests.
  2. Seal and item identifier recorded at pickup MUST be compared at delivery and return; a mismatch blocks release or refund with seal_mismatch.
  3. A Custodian's liability terms MUST state what it pays when its attestation is wrong, and it MUST revoke that attestation.

11.5 Contact and delivery details

  1. Delivery and contact details travel in UCP checkout and fulfillment objects to the marketplace; agents MUST NOT relay them between parties.

  2. When an item ships, the buyer's address goes only to the carrier or Custodian.

  3. For meetups, viewings and test drives, names and phone numbers are disclosed only after an accepted offer fixes a handover option and window.

  4. Booking a viewing or test drive before a deal is out of scope for this draft; it is expected to use UCP Local Services once that exists.

12. Transport bindings

One JSON Schema per operation is the source of truth; REST, MCP and A2A bindings follow UCP's bindings and are generated from it. Decision semantics are identical on every transport. On MCP, a marketplace exposes RCTP verbs as tools on UCP's MCP transport, unchanged; the tool result carries the decision, and a forbid is a JSON-RPC error -32000 with the registered reason in error.data.code. The binding names the tools.

Operation REST
Create, counter, accept, decline, get an offer POST /offers, POST /offers/{id}/counter, /accept, /decline, GET /offers/{id}
Create a listing; change its terms POST /listings, POST /listings/{id}/terms
Read an approval; answer it (approval page) GET /approvals/{id}, POST /approvals/{id}/response
Redeem a checkout POST /deals
Write and read deal events POST /deals/{id}/events, GET /deals/{id}/events

13. Reason codes

Every refusal carries exactly one registered reason.

Reason HTTP When
signature_invalid 401 The signature or key binding fails, or the marketplace requires a signature and there is none
operator_unknown 401 The operator's UCP profile cannot be resolved, or the operator is not onboarded
grant_invalid 401 The grant is missing, unknown, or not bound to the signing key
grant_revoked 403 The seller or operator revoked the grant
grant_expired 403 The grant is past exp
action_forbidden 403 The verb is forbid, not granted, or not the caller's to use
not_in_scope 403 The listing is not the seller's, has no terms, or is closed
below_floor 403 Under the seller's floor; no private term is ever stated
counterparty_requirements_unmet 403 The buyer falls short of the listing's requirements
buyer_authority_exceeded 403 Outside the buyer's AP2 mandate
protected_payment_required 403 Protected payment is required
approval_invalid 403 An approval's signature, challenge, expiry or single use fails
approval_surface_not_allowed 403 Wrong approval level, or above the certified cap
approval_timeout 403 An ask expired with no answer
terms_invalid 422 Listing terms or Deal Terms break the term set or the listing's options, or supersedes names an offer outside the negotiation
custody_attestation_invalid 422 A custody attestation does not bind to this listing or item
offer_expired 409 The offer or counter passed expires_at
listing_reserved 409 Another accepted offer holds the listing (7.4)
offer_replayed 409 An accepted offer's nonce was already used
release_condition_unmet 409 Money requested before its condition holds (10.3)
seal_mismatch 409 Seal or item identifier differs from pickup
offer_budget_exhausted 429 Too many below-floor offers (8.5)

14. Security considerations

Threat Control Section
An agent is persuaded or injected into a bad deal Terms enforced by the platform; structured facts only 6, 8, 11.3
The seller's own agent leaks the floor The marketplace never discloses private terms; whatever an agent says, no sale happens below the floor; a marketplace may keep the floor from every agent 6.1, 6.4, 8
A buyer binary-searches the floor No floor in refusals or records; per-agent and per-operator budgets 8.2, 8.5
An accepted offer is replayed or altered Single-use, business-signed checkout bound to Deal Terms 7.4
Two buyers each get a checkout for one item Acceptance reserves the listing; one checkout at a time 7.4
A change of terms after acceptance reprices the deal Accepted Deal Terms are fixed 7.4
A stolen agent key or token keeps acting Grant checked live on every call; key-bound when signed; revocable at any time 5
Fake approvals; a partner shows one thing and the seller signs another Seller's own key over a challenge bound to action, amount and terms; displayed-text digest 9
Funds released early Release only on signed events, by the holder of funds 10.3
"You sent me a brick"; swapped returns Seal and identifier compared at pickup, delivery, return 11.4
A relayed event is wrong Relayed entries name their source; required_observation per category 10
Farmed reputation Published, reviewed methodology; linked accounts excluded 11.1
Over-shared identity data Derived facts only 11.2
Agents bypass the enforcement point Every agent path goes through the enforcement point; which authentication mechanisms it accepts is the marketplace's choice, and each call records its mechanism 4.1
An unsigned call is disputed The record states the mechanism, profile and client; the marketplace sets what each mechanism may do 4.1, 8.4
A leaked bearer token is replayed Short-lived access tokens, refresh-token rotation, live grant check on every call, revocation 4.1(7), 5.3, 5.4
The agent host sees the conversation The host is not bound by 4.1(4); the operator's duties live in its client registration; the marketplace sets tiers per mechanism 4.1(5), 8.4
A compromised enforcement point Its entries are signed and chained 10

Marketplace APIs MUST honour grant scopes. A grant in front of an API that ignores scopes is a promise, not a control.

15. Privacy considerations

An issuer learns only from events it is party to.

Channel Rule
Check No per-presentation signal; status lists are shared
Refresh The holder's own refreshes only
Settlement A record only when the holder submits it; counterparties as pairwise pseudonyms
Dispute A record for that case only, with stated retention
Fraud One credential with evidence; the holder is notified and may appeal
Aggregates Opt-in counts with differential privacy, published to every member
Billing Metered per verifier, not per holder
  1. No credential lookup keyed by a person or account identifier.
  2. No change to bands, fees or ranking because a holder traded elsewhere.
  3. No RCTP data for advertising or targeting.
  4. The platform discloses private terms only to the seller (6.4).
  5. No RCTP object carries addresses, phone numbers, identity numbers or names.
  6. Bands are automated profiling: holders need access, correction and objection under each market's data protection law, and issuers need legal advice on whether credentials are consumer reports.

16. Registries

Registries are versioned files in the specification repository. Additions need editor review; removals need a new major version. Open values (4.5) need no registration.

Registry Values
Credential types credential.counterparty.1, credential.identity.1, passport.item.1, attestation.transaction.1
Verbs Section 8.4, with reference default and allowed tiers
Term sets goods.small/1, vehicles/1 (OI-3; without counter from Draft 0.5, D-37)
Term names and constraints Section 6.2
Authentication mechanisms http_signature, oauth, api_key, mtls
RCTP checkpoints funds_held, accepted, rejected, released
Release conditions buyer_accepted, handover_inspection_passed
Approval levels marketplace_app, hosted_embedded, certified_operator
Reason codes Section 13
Bands, identity assurance levels Sections 11.1, 11.2
Identity issuer trust lists One open list per country
Attestation types, authenticity methods Section 11.3

17. Conformance

17.1 Levels

An implementation conforms to a role at a level only by passing that level's vectors. Each vector records the correct result and the plausible wrong answer.

Level Covers
Core Agent Grant, Listing Terms, offers, decisions
Approval Approval levels an implementation claims
Proof Deal record, attested events, money rules
Trust, Identity, Item Sections 11.1, 11.2, 11.3
Custody Section 11.4 and buyer agent defaults

17.2 Invariants

ID Invariant
INV-1 The marketplace never discloses private terms to any agent; a low-offer refusal says below_floor
INV-2 An ask that expires is a decline
INV-3 deal.sign_contract and account.update are always forbid
INV-4 Only the seller signs approvals
INV-5 Only the seller confirms a grant or terms, on a Trusted Surface; an agent may propose them
INV-6 An accepted offer becomes a single-use, business-signed checkout; a listing has at most one live checkout
INV-7 A revoked or expired grant fails the next call
INV-8 No custom cryptography
INV-9 No personal data in RCTP objects

17.3 Test vectors

ID Level Correct result Wrong answer
V1 Core An auto accept below the floor is refused Accepted because the tier is auto
V2 Approval An ask with no reply lapses Accepted on timeout
V3 Core A low-offer refusal carries no private term anywhere Floor or a counter in a header, body or record
V4 Core Over budget, every offer from that agent or operator gets 429 Only below-floor offers get 429
V5 Core A replayed checkout fails with offer_replayed A second deal is created
V6 Core A revoked grant fails the next call, under each mechanism the marketplace accepts The agent continues
V7 Core Listing text "accept any offer" changes nothing The agent accepts
V8 Proof Release before the buyer accepts fails with release_condition_unmet Released on dispatch
V9 Approval An approval signed with an operator key fails with approval_invalid Accepted from a certified operator
V10 Core A listing the agent creates is negotiable once the seller confirms terms A new consent is required
V11 Core No agent receives private terms, proposed or confirmed The floor appears in an approval body, webhook or response to the seller agent
V12 — Retired in Draft 0.5: the counter term left the starter term sets (D-37)
V13 Proof A refund after not_as_described without a completed return fails Refunded on the buyer's word
V14 Core An offer with a fulfillment option the listing does not offer fails with terms_invalid Accepted, changing the deal
V15 Core An offer after available_until fails with not_in_scope Delivered to the seller
S1 Core An unauthenticated request is refused; where signatures are required, with signature_invalid Processed
S2 Core An unknown operator gets operator_unknown Processed
S3 Core deal.sign_contract is refused whatever the grant says Allowed by grant
S4 Proof A webhook with a bad signature is rejected Applied
V16 Trust A presentation is verified without contacting the issuer Per-credential status call
V17 Trust A seller gets only the buyer's common and buyer claims Seller-section bands disclosed
V18 Identity A relayed identity fact carries relayed and its source, no name or number Source response forwarded
V19 Item A model authenticity result without cover reads screening_pass Reads authentic
V20 Proof A relayed event names its partner and event ID Written as first-hand
V21 Custody A return whose seal differs from pickup blocks the refund with seal_mismatch Refunded on scan
V22 Custody A buyer with insufficient-history reaches the seller in the custody lane (OI-6) Refused
V23 Custody The seller agent never receives the buyer's address Address in the order
V24 Custody A buyer agent asked to pay outside the platform raises an ask It pays
V25 Core An offer outside the buyer's AP2 mandate fails with buyer_authority_exceeded Reaches the seller
V26 Core A second offer.accept on a reserved listing fails with listing_reserved Two checkouts for one item
V27 Core listing.set_terms or listing.reprice after acceptance leaves the checkout's Deal Terms unchanged The checkout is repriced or ended
V28 Core Accepting an offer or counter after its expires_at fails with offer_expired Accepted days later
V29 Core An offer that names a counter in supersedes sets it superseded Both stay acceptable
V30 Core A call authenticated by OAuth is admitted where the marketplace accepts OAuth, and recorded with authenticated_by oauth Refused, or recorded as signed
V31 Core listing.set_terms returns ask whatever the grant's tiers Terms changed without the seller
V32 Core Proposed terms appear pre-filled on the seller's confirmation, and only the confirmed values are stored and enforced The proposed floor is enforced, or stored, without confirmation
V33 Core Every entry for an agent call carries authenticated_by and agent_profile, and client_id for OAuth The mechanism or client is missing from the record
V34 Core A key-bound token on a request signed by a different key is refused grant_invalid Processed under the token's grant
V35 Core A UCP-Agent that does not match the profile registered for the OAuth client is refused operator_unknown Processed under the claimed profile

Vectors that assert a tier read the marketplace's published default_tier and allowed_tiers (8.4), not the reference table. Vectors that exercise offer.counter (the counter steps of V11, V28 and V29) run only where the marketplace offers dev.rctp.deal:offer_counter.

17.4 Starter profile

A first deployment MAY claim the Starter profile: Core with goods.small/1; Approval at hosted_embedded; Proof with funds_held, accepted, rejected, released and UCP return and refund. Trust, Identity, Item and Custody are added when a verifier, partner or arbiter asks for them. A Starter deployment MAY offer floor defence only, without offer.counter (7.3(5)), and MAY accept any authentication mechanism UCP allows (4.1).

17.5 Promotion to Draft 1.0

Draft 1.0 requires two independent implementations, built by teams that share no code, in different jurisdictions. Each passes every vector at its claimed levels, and the two complete an end-to-end trade with each other.

18. References

Normative

  • BCP 14: RFC 2119 and RFC 8174
  • RFC 6749 and RFC 7636 (OAuth 2.0, PKCE); RFC 6750 (bearer tokens); RFC 8705 (mTLS); RFC 7009 (token revocation); RFC 7800 (proof-of-possession key semantics); RFC 9396 (Rich Authorization Requests)
  • RFC 7638 (JWK thumbprint); RFC 8785 (JSON canonicalization)
  • RFC 9421 (HTTP Message Signatures); RFC 9530 (Digest fields); RFC 9651 (Structured Field Values)
  • RFC 9901 (SD-JWT); draft-ietf-oauth-sd-jwt-vc; draft-ietf-oauth-status-list
  • W3C Web Authentication Level 3
  • UCP specification: Signatures, Identity Linking, Ask, Checkout, Fulfillment, Payment Terms, Order, and the MCP transport. Release v2026-08-25; Ask at commit f2626c2 until released.
  • AP2 v0.2: Checkout Mandate, Payment Mandate

Informative

Appendix A. Examples

Illustrative only. Identifiers, amounts and URLs are invented.

A.1 Agent Grant (introspection view, held by the marketplace)

{
  "grant_id": "grt_01KA3M7Q",
  "seller": "pp:7f2c",
  "operator": "https://agents.example/.well-known/ucp",
  "agent_id": "agt:seller:7c1f",
  "cnf": { "jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" },
  "scopes": ["dev.rctp.listing:create", "dev.rctp.listing:answer_buyer", "dev.rctp.deal:offer_counter", "dev.rctp.deal:offer_accept"],
  "tiers": { "dev.rctp.deal:offer_accept": "ask" },
  "iat": 1792540800, "exp": 1800316800, "status": "active"
}

A.2 Listing Terms (stored by the platform; never sent to an agent)

{
  "listing_id": "lst_camera_x100",
  "term_set": "goods.small/1",
  "terms": {
    "floor": { "value": 300, "currency": "SGD" },
    "available_until": "2026-11-21T00:00:00Z",
    "fulfillment_options": ["shipping", "meetup"],
    "release_condition": "buyer_accepted",
    "deliver_within_days": 7
  },
  "terms_commitment": "sha-256:5b1e..."
}

A.3 Offer with Deal Terms

{
  "offer_id": "ofr_01KB2R9T",
  "negotiation_id": "neg_01KB2Q4M",
  "supersedes": "ofr_01KB2Q8C",
  "expires_at": "2026-10-29T12:00:00Z",
  "listing_id": "lst_camera_x100",
  "price": { "value": 335, "currency": "SGD" },
  "fulfillment": { "method_type": "shipping", "selected_option_id": "std" },
  "payment": { "selected_term_id": "pay_now_held" }
}

A.4 Decisions

HTTP/1.1 403 Forbidden
RCTP-Decision: forbid;action="offer.create";reason=below_floor

HTTP/1.1 202 Accepted
RCTP-Decision: ask;approval_id="apr_01K8ZB7";expires_in=900;on_timeout=deny

HTTP/1.1 429 Too Many Requests
RCTP-Decision: forbid;reason=offer_budget_exhausted;retry_after=3600

A.5 Deal record entries

[
  { "seq": 1, "author": "ep:marketplace.example", "action": "offer.create", "tier": "forbid", "result": "below_floor", "offered": 250, "authenticated_by": "http_signature", "agent_profile": "https://buyer-agents.example/.well-known/ucp" },
  { "seq": 2, "author": "ep:marketplace.example", "action": "offer.accept", "tier": "auto", "result": "accepted", "terms_commitment": "sha-256:5b1e...", "authenticated_by": "oauth", "agent_profile": "https://agents.example/.well-known/ucp" },
  { "seq": 3, "author": "pay:holder.example", "event": "funds_held", "observation": "first_hand" },
  { "seq": 4, "author": "carrier.example", "event": "shipped", "observation": "first_hand", "evidence": { "tracking_ref": "sha-256:9a0c..." } },
  { "seq": 5, "author": "ep:marketplace.example", "event": "delivered", "observation": "relayed", "reported_by": "carrier.example", "source_event_id": "evt-55821", "location": "Singapore" },
  { "seq": 6, "author": "pp:buyer-3d1a", "event": "accepted" },
  { "seq": 7, "author": "pay:holder.example", "event": "released", "observation": "first_hand" }
]

A.6 Party Credential presentation (a buyer's disclosed claims)

{
  "vct": "credential.counterparty.1",
  "disclosed": {
    "identity_assurance": { "level": "gov_eid", "source": "VNeID", "observation": "relayed" },
    "buyer.completed_purchases_band": "10-49",
    "buyer.adverse_findings_band": "0"
  },
  "kb_jwt": { "aud": "ep:marketplace.example", "nonce": "n-5f2c" }
}

A.7 Proposed terms (the seller said "list at 400, not below 300")

{
  "title": "Camera X100, boxed",
  "category": "cameras",
  "condition": "like_new",
  "price": { "value": 400, "currency": "SGD" },
  "term_set": "goods.small/1",
  "proposed_terms": { "floor": { "value": 300, "currency": "SGD" } }
}

The marketplace answers ask (or creates the listing at auto, without terms) and shows the seller a form pre-filled with the floor and its category defaults. The agent learns terms_commitment once the seller confirms, never the value.

Appendix B. Resolved open issues

B.1 Draft 0.5

Raised in the Draft 0.5 proposal and decided by the editor on 10 November 2026, subject to lazy consensus until 17 November 2026.

ID Question Resolution Section
OQ-1 Do deal.sign_contract and account.update stay fixed forbid? Yes: signing contracts and changing account details are outside a trade, so the rule concerns scope, not posture (D-39) 8.4, INV-3
OQ-2 Which UCP profile does a plugin without its own use? Its developer's, as operator; or one the marketplace hosts per registered OAuth client (D-40). A call without UCP-Agent uses the profile registered for its OAuth client (D-42) 4.1(1), 4.1(5)
OQ-3 Field names for how a call authenticated authenticated_by and agent_profile, on deal record entries (D-34) 4.1(6), 10.1
OQ-4 May the seller's agent know the floor? Yes; pre-fill is the expected flow (D-36). Replaces OI-1 and OI-5 6.1, 6.4

B.2 Draft 0.4

Raised and resolved in #21; every resolution is decision D-31. OI-1, OI-2 and OI-5 are superseded in Draft 0.5 by D-36, D-35 and D-36.

ID Question Resolution Section
OI-1 May the seller agent pre-fill suggested terms? No 6.1
OI-2 Default tier for offer.accept within terms ask; the seller may choose auto 8.3, 8.4
OI-3 First term sets goods.small/1, vehicles/1; property later 6.2, 16
OI-4 Grant lifetime and idle expiry At most 90 days, renewed by refresh; earlier idle expiry at the marketplace's choice 5.2
OI-5 May a seller let their own agent see the floor? No 6.4
OI-6 Draft 0.3 [9.2(4)]: fixed rule or recommended default? Kept as a rule 8.6
OI-7 RCTP scope names Scopes under dev.rctp.listing and dev.rctp.deal (D-29, D-30) 8.4
OI-8 UCP release to pin v2026-08-25; UCP Ask at commit f2626c2 until released 1.4, 18
OI-9 When to propose the offer part of dev.rctp.deal to UCP #502 After this review; to discussions #502 and #812, as a vendor-namespaced capability with vectors —
OI-10 Capability version string and overlap with 2026-10-draft3 2026-11-draft4; 2026-10-draft3 served beside it for at most 90 days 4.5
OI-11 Decision header name RCTP-Decision 8.2
OI-12 Booking viewings and test drives before a deal Out of scope; UCP Local Services once it exists 11.5
OI-13 Offer capability name, given UCP's Offer extension (#738, #773) dev.rctp.deal (D-29) 7.1

Appendix C. Decisions and changes

C.1 Decision log

Every decision was adopted by the editors; D-20 to D-31 were confirmed in #21.

ID Date Decision Why Status Sections
D-1 2026-10-14 Names dev.rctp.* under rctp.dev; capability version 2026-10-draft3; Starter profile first Neutral namespace from day one; smallest useful slice Adopted 4.5, 17.4
D-2 2026-10-18 Split the Seller Mandate into Agent Grant and Listing Terms The mandate keyed floors by listing ID at connect time, so listings the agent created later could not be negotiated Adopted 5, 6
D-3 2026-10-18 The seller's permission is platform-local, not a verifiable credential It is not enforced by any other party; revocation becomes live Adopted 5
D-4 2026-10-18 Accepting within terms is a per-seller tier Some sellers want speed, others control Adopted 8.3
D-5 2026-10-18 A floor is enough; other terms vary per category through term sets One protocol, category-appropriate safeguards Adopted 6.2
D-6 2026-10-20 The seller sets terms on the hosted page; no agent receives them An agent cannot leak what it never had Adopted 6.1, 6.4
D-7 2026-10-20 Offer budget per buyer agent with an operator ceiling One abusive user should not lock out a whole operator Adopted 8.5
D-8 2026-10-20 Refunds: not_as_described needs a completed return; not_received after the delivery window Close "keep the item and the money" and "never shipped" Adopted 10.3
D-9 2026-10-21 Minimum core on UCP and AP2: reuse what exists, keep five things Simplicity is the ultimate complexity Adopted 1.3, 1.4
D-10 2026-10-21 RCTP covers proof and Deal Terms; booking, quotes and tracking stay with UCP and carriers Do not redefine existing verbs Adopted 1.1, 7.2
D-11 2026-10-21 The holder of funds is a role: the AP2 payee Works for managed marketplaces and licensed payment partners Adopted 7.5, 10.2
D-12 2026-10-21 Carrier- or inspector-signed checks are an optional category term No opinion in the core Adopted 6.2, 10.3
D-13 2026-10-21 Buyer requirements are a Listing Terms requirement set by the seller The seller's preference, enforced by the platform Adopted 6.2
D-14 2026-10-21 Agent identity is the UCP profile and UCP-Agent; the operator record is retired UCP already defines it Adopted 4.1
D-15 2026-10-21 The Agent Grant is UCP Identity Linking with RCTP scopes and key binding UCP already defines OAuth scopes Adopted 5
D-16 2026-10-21 UCP signed webhooks replace the RCTP webhook format UCP already defines them Adopted 1.4
D-17 2026-10-21 Events over UCP order events; RCTP keeps funds_held, accepted, rejected, released UCP covers shipping and money adjustments Adopted 10.2
D-18 2026-10-21 Offers carry Deal Terms; listings carry available_until Agents agree the whole deal, within a listing window Adopted 6.2, 7.2
D-19 2026-10-21 Six fixed rules; everything else is an open value Minimal core, extensible by category Adopted 1.3
D-20 2026-10-21 terms_invalid also covers Deal Terms the listing does not allow One reason for one class of error Adopted 7.2, 13
D-21 2026-10-21 Handover options are part of Deal Terms; the separate handover capability is dropped One place to agree how the item changes hands Adopted 11.5
D-22 2026-10-21 Starter profile: Core, Approval at hosted_embedded, Proof money events; item checks added on demand Matches what v0.1 proved Adopted 17.4
D-23 2026-10-21 Deal events written at POST /deals/{id}/events One route for all attested events Adopted 12
D-24 2026-10-27 Accepting an offer reserves the listing; other accepts get listing_reserved Second-hand items are single units; an auto accept could otherwise create two checkouts Adopted 7.4, 8.1, 13
D-25 2026-10-27 Accepted Deal Terms are fixed until the checkout is redeemed or expires; only a seller withdrawal ends it early The platform makes a firm commitment; later term changes must not reprice a deal Adopted 6.3, 7.4
D-26 2026-10-27 Every offer and counter has expires_at, capped at available_until Async negotiation must not leave offers open indefinitely Adopted 7.3
D-27 2026-10-27 Offers carry negotiation_id and supersedes Durable identity and revision across counters, as UCP discussion #812 asks Adopted 7.2
D-28 2026-10-27 The offer capability is standalone and produces a checkout, not a checkout extension Offers exist before any checkout; matches the separate-artifact model in UCP #812 Adopted 7.1
D-29 2026-10-27 Two capabilities: dev.rctp.listing and dev.rctp.deal (offers through the deal record); every seller scope sits under one of them; fixed forbid verbs have no scope "Offer" clashes with UCP's merchant Offer extension (#738, #773); "deal" is already the draft's word for the trade, and both sides should get a good one; scopes must name a real capability Adopted 1.4, 5.2, 6.2, 7.1, 8.4
D-30 2026-10-27 order.commit_to_ship becomes deal.commit_to_ship; passport.disclose_full_report becomes deal.disclose_passport Every seller verb reads listing.*, offer.* or deal.*, so its prefix names its capability Adopted 8.4
D-31 2026-10-27 Draft 0.4 adopted for v0.2; open issues OI-1 to OI-13 resolved as listed in Appendix B Editor review complete (#21) Adopted 1.4, 4.5, 5.2, 6.1, 6.4, 8.2, 11.5, B
D-32 2026-10-27 Erratum: RCTP scopes are declared in dev.ucp.common.identity_linking config.scopes, as every UCP scope is, not in the RCTP capability configs UCP Identity Linking defines one place for scopes; D-29 had moved them Adopted 5.2, 7.1
D-33 2026-11-10 The offer state requires_escalation becomes waiting_approval; an RCTP offer is not UCP's Offer extension, and offer.* keeps its name (D-29) unless that extension merges with an offer field our agents meet in the same flow In UCP, requires_escalation means "hand the buyer to a browser" and makes continue_url a MUST (#81) Adopted 7.1, 7.3
D-34 2026-11-10 Authenticate as UCP does: signatures recommended; OAuth, API keys or mTLS where the marketplace accepts them; tokens key-bound only when signed; every entry records authenticated_by and agent_profile Draft 0.4 was stricter than UCP and refused plugins on agent hosts that cannot sign; the floor, the live grant and the record protect a trade whatever the mechanism (#92) Adopted, lazy consensus to 2026-11-17 4.1, 5.3, 5.4, 8.1, 10.1, 14
D-35 2026-11-10 Tier policy belongs to the marketplace: the 8.4 table becomes reference defaults; listing.create may be auto; listing.set_terms always opens the seller's confirmation The profile defines verbs, scopes and invariants; marketplaces set policy. A marketplace whose sellers already let their agent act could not offer the same experience (#91) Adopted, lazy consensus to 2026-11-17 6.1, 6.3, 8.4
D-36 2026-11-10 Listing Terms in plain language: two prices are the minimum; a seller agent may propose terms, the floor included, shown pre-filled and stored only when the seller confirms; public terms default from the marketplace; INV-1 and INV-5 restated Everything about the item reaches the marketplace through the seller's agent anyway, so hiding the floor from that one agent buys little and costs the seller a second entry. The value is that the marketplace never discloses the floor to any other agent and never sells below it (#94) Adopted, lazy consensus to 2026-11-17 2, 3, 6, 9.2, 14, 17.2
D-37 2026-11-10 The counter term leaves the starter term sets and below_floor carries no private value; seller counter-offers are optional for a marketplace; floor defence alone is complete "Counter" read as a second price every seller must set; no marketplace asked for a fixed counter (#94). A later term set can bring it back Adopted, lazy consensus to 2026-11-17 6.2, 7.3, 8.2, 8.3, 13, 17.3
D-38 2026-11-10 RCTP's story is delegated by consent, transparent profiles, guardrails enforced, replacing "agents propose, the marketplace decides, signatures prove" RCTP's value is full delegation that people can trust, not how a call is handled Adopted Abstract, 1.2
D-39 2026-11-10 INV-3 stays: deal.sign_contract and account.update are always forbid They are outside a trade, so the rule concerns scope, not posture Adopted 8.4, 17.2
D-40 2026-11-10 A plugin without its own UCP profile uses its developer's, or one the marketplace hosts per OAuth client UCP requires a profile for every caller; either keeps an accountable operator Adopted 4.1
D-41 2026-11-10 Draft 0.5 is the implementation baseline, capability version 2026-11-draft5; dev.rctp.* is backed by rctp.dev A first marketplace phase should carry no workarounds for rules this draft removes Adopted Status, 4.5
D-42 2026-11-10 Review of #92: an OAuth call without UCP-Agent uses the profile registered for its client, and a present one must match; operators without a profile accept their duties in the client registration; the agent host is not bound by 4.1(4); entries carry client_id; the bearer-token controls are named; vectors V34 and V35 Plugins on agent hosts cannot add UCP-Agent, so every plugin call would have been refused; the record must say who, not just how (#92 review, B-13) Adopted, lazy consensus to 2026-11-17 4.1, 5.3, 10.1, 14, 17.3
D-43 2026-11-10 The offer state is awaiting_approval, not waiting_approval (supersedes the name in D-33) Agreed with the first marketplace implementer before any implementation shipped; reads as the state of the offer ("awaiting the seller's approval") Adopted, lazy consensus to 2026-11-17 7.3

C.2 Resolved ambiguities from v0.1

ID Question Resolution Section
A-1 How the enforcement point receives the mandate Dissolved: no mandate travels; a key-bound token does 5.3
A-2 SD-JWT+KB for the mandate Dissolved: no credential is presented to the enforcement point 5.3
A-3 Reason for an unverifiable mandate grant_invalid, grant_revoked, grant_expired 13
A-4 Counter equal to the floor Term-set constraint counter > floor 6.2
A-5 Offers after the budget is spent All get 429; budget per agent with operator ceiling 8.5
A-6 Action for an inbound offer offer.create 8.3
A-7 Listing scope; missing floor Dissolved: the seller's listings with terms 6.5
A-8 Floor on the seller's counter Yes, and on reprices 8.3
A-9 Who accepts Seller side only; a counter is an invitation 7.3
A-10 Late approval reason approval_invalid; approval expired with approval_timeout 9.3
A-11 Status-list caching versus next-call failure Dissolved: grants are checked live 5.4
A-12 What precedes refunded Rules 10.3(2)–(3) 10.3
A-13 Seller passkey registration The existing marketplace account passkey 9.3
A-14 Routes for checkout, events, fixed forbids Section 12; fixed forbids need no route 12

C.3 Change history

Version Date Status Changes
Draft 0.2 — Superseded Verified custody; buyer agent defaults; credential hardening; consumer-reporting check; two-implementation rule for Draft 1.0
Draft 0.3 2026-10-10 Superseded; implemented by v0.1.0-draft.3 Seller and buyer sections in the Counterparty Credential; identity facts module; contact and delivery disclosure by stage; owner and return-match attestations; first-hand and relayed checkpoints mapped to EPCIS; partner operator obligations; AP2 buyer authority; approval interface; Starter profile
Draft 0.4 2026-10-21 Editor's draft Agent Grant and Listing Terms replace the Seller Mandate (D-2 to D-8); minimum core on UCP and AP2 (D-9 to D-19); offers with Deal Terms; deal record over UCP order events; operator record and RCTP webhooks retired; reason codes grant_* and terms_invalid; invariants INV-1, INV-5, INV-7 restated; vectors V10–V15 added; all fourteen v0.1 ambiguities resolved (C.2)
Draft 0.4 2026-10-27 Editor's draft Review fixes D-24 to D-30: listing reservation and listing_reserved; fixed Deal Terms after acceptance; expires_at on every offer; negotiation_id and supersedes; capabilities dev.rctp.listing and dev.rctp.deal with scopes under them (OI-7, OI-13 resolved); verbs deal.commit_to_ship and deal.disclose_passport; INV-6 restated; vectors V26–V29
Draft 0.4 2026-10-27 Adopted for v0.2 Open issues OI-1 to OI-13 resolved (D-31); UCP v2026-08-25 pinned; capability version 2026-11-draft4
Draft 0.4 2026-10-27 Adopted for v0.2, erratum D-32: scopes declared in UCP Identity Linking config.scopes
Draft 0.5 2026-11-10 Editor's draft, implementation baseline The Draft 0.5 proposal (D-33 to D-41): the story; authentication as UCP does it, with authenticated_by and agent_profile; tier policy owned by the marketplace; Listing Terms in plain language with proposed terms; the counter term removed and offer.counter optional; waiting_approval; INV-1, INV-5 and INV-7 restated; S1 restated; V12 retired; vectors V30–V33; capability version 2026-11-draft5
Draft 0.5 2026-11-10 Editor's draft, review fixes D-42 from the #92 review: OAuth calls without UCP-Agent, operator duties in the client registration, the agent host, client_id on entries, bearer-token controls, V34 and V35
Draft 0.5 2026-11-10 Editor's draft, naming fix D-43: the offer state is awaiting_approval

Source: spec/rctp-draft-0.5.md