Specification
About the specDraft 0.5v0.3 bindingAmbiguitiesSpec changelogDraft 0.4 proposal: Listing Terms and Agent Grants
Status: adopted for v0.2 on 27 October 2026 (#21); superseded by
Draft 0.4, which is the normative text. Where this proposal and the draft differ, the draft wins.
This proposal keeps the reasoning. · Proposed 20 October 2026 · Replaces Draft 0.3 section 4 (Seller Mandate) if
adopted · Resolves A-1 to A-14 in ../AMBIGUITIES.md · Revised 21 October: section 13 aligns
the proposal with UCP and AP2 and overrides earlier sections where they differ · Incorporated into the
Draft 0.4 editor's draft, which is the text to review; this proposal keeps the reasoning
Section numbers in brackets, such as [4.1], refer to Draft 0.3. Key words follow BCP 14 and apply to the proposed text only.
Summary
- Two objects replace the Seller Mandate. An Agent Grant says which agent may act for which seller and with which verbs. Listing Terms say what the seller will accept for one item.
- The seller sets terms once per item, when they ask their agent to list it. The platform holds the terms privately and enforces them on every call. No agent, buyer or seller, ever receives the floor.
- Buyers get a deterministic answer. Below the floor: refused, with the seller's counter if they set one. At or above: delivered to the seller agent, which negotiates.
- Terms adapt per category through term sets: a floor everywhere, plus deposits, inspections or delivery windows where the category needs them.
- The grant is local to the platform. It is an OAuth 2.0 grant bound to the agent's key, not a verifiable credential. Revocation takes effect on the next call, with no status list. Portable credentials remain for facts that travel: identity [5] and items [6].
- All fourteen v0.1 ambiguities close. Five disappear with the mandate, nine get a firm rule (section 9).
- Minimum core on UCP and AP2 (section 13). RCTP reuses every verb and noun UCP or AP2 already defines, and keeps five things of its own: offers, Listing Terms, the decision, signed proof of who did what, and portable credentials.
1. Why change
Peer review found the mandate confusing, and the v0.1 build shows why. The mandate is signed once, at connect time, but
it keys price_floor by listing ID [4.1]. A listing the agent creates later has no floor: buyer offers on it bypass the agent and reach
the seller as ordinary marketplace offers, and the agent's own counters and accepts are refused not_in_scope (A-7). The v0.1 seller-agent sample lists an item and then cannot negotiate on it. The only fix
in Draft 0.3 is a fresh consent on the issuer's page for every new listing, after the seller has already approved the
listing itself.
The mandate also bundles three things with different lifecycles:
| Bundled in the mandate today | Changes when | Belongs to |
|---|---|---|
| Which agent acts for the seller, and with which verbs | Rarely: connect, disconnect | The seller's account |
| Floor, counter, reprice band, deposits | Every time an item is listed or repriced | The listing |
| Offer budget, approval surfaces, timeouts | Never per seller | Platform policy |
Three questions put to the editors on 18 October settled the direction:
- Will a seller's permission ever be enforced by a party other than the platform that issued it? Not likely. A verifiable credential buys nothing here; a platform-local grant is enough.
- May the seller agent accept within the terms without asking the seller each time? Maybe. It stays a per-seller
choice, with
askas the default. - Is a floor enough, or do terms also need an auto-accept price? A floor is enough, but terms must vary by category.
This narrows repository decision 4 (multi-issuer) in ../README.md: it keeps applying to portable
credentials [5, 6], and no longer to the seller's permission for an agent.
2. The model
sequenceDiagram
autonumber
actor S as Seller
participant SA as Seller agent
participant P as Platform (enforcement point)
participant BA as Buyer agent
S->>P: Connect agent once (consent page)
P-->>SA: Agent Grant, bound to the agent's key
S->>SA: "List my camera"
SA->>P: listing.create (item, list price)
P-->>SA: 202 ask
S->>P: Hosted page: confirm item, set terms (floor 300), passkey
P-->>SA: Listing live (terms stay with the platform)
BA->>P: offer.create 250
P-->>BA: 403 below_floor, counter 340
BA->>P: offer.create 320
P-->>SA: Offer delivered
SA->>P: offer.counter 335
P-->>BA: Counter 335
BA->>P: offer.create 335
SA->>P: offer.accept
P-->>BA: Single-use checkout
The seller touches the system twice: once to connect the agent, once per item to approve the listing with its terms.
Draft 0.3 already makes listing.create an ask in every category [15.2], so the second touch adds no step.
3. Agent Grant (replaces [4])
3.1 What it is
An Agent Grant is the seller's permission for one agent to act for them on one marketplace. It is a record held by the marketplace, issued through OAuth 2.0, and presented as an access token bound to the agent's key. It carries no prices and no listings.
| Field | Content |
|---|---|
grant_id |
grt_ followed by a unique identifier |
seller |
Pairwise pseudonymous seller ID, scoped to the marketplace and the operator. No personal data (INV-9). |
operator_id, agent_id |
From the operator record [8] |
cnf.jkt |
RFC 7638 thumbprint of the agent key the grant is bound to |
verbs |
The registered actions the agent may use (section 5.3). The fixed forbids can never be granted. |
tiers |
Optional per-verb overrides, only within each verb's allowed tiers (section 5.3) |
consent |
Consent screen version and time; identity assurance of the account. Kept by the marketplace, not in the token. |
iat, exp |
Issue and expiry times. Lifetime is marketplace policy; RECOMMENDED at most 90 days, renewed by refresh. |
status |
active, revoked or expired |
3.2 Issuance
- The marketplace's authorization server MUST issue a grant only after the seller confirms it on a Trusted Surface that names the agent, its operator, every verb with its tier, and the expiry, in plain language.
- Issuance uses the authorization code flow with PKCE (RFC 7636) and RFC 9396 authorization details of type
dev.rctp.agent_grantcarryingverbsandtiers. - The consent screen MUST NOT ask for prices. Prices belong to Listing Terms (section 4).
3.3 Use on every call
- The agent sends the grant's access token in
Authorization: Bearer <token>. The token format is the marketplace's choice: opaque, or a JWT access token (RFC 9068). - The token MUST be sender-constrained with
cnf.jkt(RFC 7800). The enforcement point MUST check that the RFC 9421keyidequalscnf.jktand that the request signature coversauthorization. No separate DPoP proof is needed: every request is already signed with the bound key. - The enforcement point MUST look the grant up on every call and refuse a grant that is unknown, revoked, expired or bound to another key (section 7).
3.4 Revocation
- The seller can revoke a grant at any time in the marketplace app. Operators can revoke their own tokens (RFC 7009).
- A revoked or expired grant MUST fail the next signed call (INV-7). Because the enforcement point reads the grant's live status, no status list and no cache lifetime are involved.
3.5 Where each mandate claim goes
| Mandate claim [4.1] | Goes to |
|---|---|
accountable_human |
Grant consent, held by the marketplace |
agent |
Grant operator_id, agent_id, cnf.jkt |
inventory_scope |
Implicit: the seller's own listings that have terms (section 4.6) |
commercial (price_floor, preset_counter, reprice_band) |
Listing Terms |
actions |
Grant verbs and tiers, within registry limits |
ask (surfaces, timeout) |
Platform policy, published in discovery |
offer_budget |
Platform policy (section 5.4) |
counterparty_requirements, handover_windows, settlement_requirements |
Listing Terms, where the category's term set defines them |
4. Listing Terms (new)
4.1 What they are
Listing Terms are the seller's private negotiating envelope for one listing. The seller sets them once, on a Trusted Surface, when they approve the listing their agent proposed. The platform stores them, enforces them on every call, and never discloses the private ones to any agent or counterparty.
4.2 Setting terms
- The seller agent calls
listing.createwith the item and its public list price. It sends no terms. listing.createis alwaysask(section 5.3). The 202 response carries the approval request [9.4]; itsdisplaytext names the item and list price only.- The hosted approval page shows the listing and a terms form built from the category's term set (section 4.3). The seller fills in the terms and approves with their passkey.
- The approval challenge MUST bind the listing hash and
terms_commitment(section 4.5). The platform MUST store exactly the terms the seller signed. - The listing goes live. The seller agent learns the outcome, the term set ID and
terms_commitment, never the values.
Listings a seller creates by hand in the marketplace app follow the same rule: the app shows the same terms form.
4.3 Term sets per category
A term set defines which terms a category takes, their types and limits, and which check enforces each one. Term
sets live in a new registry, term-sets, and are versioned (goods.small/1). A listing records the term set version
it was approved under.
Every term set MUST include floor. Everything else is per category.
| Term | Type | Visibility | Enforced at | goods.small/1 |
vehicles/1 |
property.rental/1 |
|---|---|---|---|---|---|---|
floor |
money | private | offer.create, offer.counter, offer.accept, listing.reprice |
required | required | required |
counter |
money | private | sent with below_floor |
optional | optional | — |
protected_payment_only |
boolean | public | checkout [9.2] | default true |
default true |
default true |
deliver_within_days |
integer | public | refunds (section 6) | default 7 | — | — |
deposit_pct |
percent | public | deal.accept_deposit |
— | optional | required |
inspection_before_deposit |
boolean | public | deal.accept_deposit |
— | default true |
— |
handover_windows |
time slots | public | handover.book_slot |
— | optional | optional |
Each term carries constraints from a closed set, so every platform checks them the same way:
| Constraint | Meaning | Example |
|---|---|---|
min, max |
Bounds on the value | deposit_pct between 5 and 50 |
gt_term, lt_term |
Greater or less than another term | counter gt_term: floor |
lte_list_price |
At most the listing's public price | floor |
min_ratio_of_list_price |
At least this share of the public price | floor ≥ 0.2 × list price, to catch typos |
A sketch of one entry:
{
"id": "goods.small/1",
"categories": ["mobile-phones", "cameras", "consoles", "small-electronics"],
"terms": [
{ "name": "floor", "type": "money", "visibility": "private", "required": true,
"constraints": { "lte_list_price": true, "min_ratio_of_list_price": 0.2 } },
{ "name": "counter", "type": "money", "visibility": "private", "required": false,
"constraints": { "gt_term": "floor", "lte_list_price": true } },
{ "name": "protected_payment_only", "type": "boolean", "visibility": "public", "default": true },
{ "name": "deliver_within_days", "type": "integer", "visibility": "public", "default": 7,
"constraints": { "min": 1, "max": 30 } }
]
}
Rules:
- A platform MUST advertise the term sets it enforces, with versions, in its UCP profile under
dev.rctp.terms. - A platform MUST refuse terms that break a constraint, with 422
terms_invalid, before the seller can approve them. - A term named
x-…is an extension. It MUST NOT change a decision unless the platform advertises it. - Adding a term set, or a term to a new version of a set, needs no change to the protocol.
4.4 Changing terms
listing.set_termschanges a listing's terms. Its only allowed tier isask: the seller sets the new values on the hosted page, as in section 4.2.listing.repricechanges the public list price. A new price below the floor MUST be refused withbelow_floor.- Offers already open are re-evaluated against the new terms the next time any party acts on them.
4.5 Keeping private terms private
- Private terms MUST NOT appear in listing data, offers, decisions, approval request bodies, webhooks, logs a partner can read, or attestation entries (INV-1).
- Attestation entries record
terms_commitmentinstead: SHA-256 over the RFC 8785 canonical JSON of{salt, terms}, wheresaltis 128 random bits kept by the platform. A bare hash of a small number can be reversed by trying every price; the salt prevents that. - The platform discloses terms only to the seller, in the marketplace app, and to an arbiter in a dispute the seller is party to.
4.6 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, outside RCTP. A seller agent acting on it is refused not_in_scope.
5. Decisions (replaces the check order in [9])
5.1 Check order
| Step | Check | Refusal |
|---|---|---|
| 1 | Signature and operator | 401 signature_invalid, operator_unknown |
| 2 | Grant: known, bound to the signing key, active, verb granted | 401 grant_invalid; 403 grant_revoked, grant_expired, action_forbidden |
| 3 | Listing: belongs to the grant's seller, has terms, is open | 403 not_in_scope |
| 4 | Counterparty requirements, where the term set has them (later levels) | 403 counterparty_requirements_unmet |
| 5 | Terms: floor, offer budget, other enforced terms | 403 below_floor (+ counter); 429 offer_budget_exhausted |
| 6 | Tier: the grant's override or the registry default | 200 auto; 202 ask |
Buyer calls skip step 2: the buyer's permission comes from its own AP2 mandate [9.3].
5.2 Offers
| Call | By | Below the floor | At or above the floor |
|---|---|---|---|
offer.create |
Buyer agent | 403 below_floor, with counter if the seller set one; counts against the offer budget |
201: delivered to the seller agent |
offer.counter |
Seller agent | 403 below_floor |
Tier, default auto |
offer.counter |
Buyer agent | Treated as offer.create at the counter amount |
|
offer.accept |
Seller agent | 403 below_floor |
Tier, default ask; the seller may choose auto |
offer.accept |
Buyer agent | 403 action_forbidden: a counter is an invitation, not a commitment |
A buyer who agrees to a seller's counter sends offer.create at that amount. Acceptance always runs offer.accept on
the seller side, so an auto counter can never bypass an ask on accept.
5.3 Verbs and tiers
The registry gives each verb a default tier and the tiers a seller may choose. A grant may only pick from the allowed set.
| Verb | By | Default | Allowed | Notes |
|---|---|---|---|---|
listing.create |
seller agent | ask |
ask |
Terms are set at this approval |
listing.set_terms |
seller agent | ask |
ask |
New verb |
listing.reprice |
seller agent | auto |
auto, ask |
Never below the floor |
listing.answer_buyer |
seller agent | auto |
auto, ask |
Answers from structured listing facts |
offer.create |
buyer agent | — | — | New verb; checked against terms, no tier |
offer.counter |
seller agent | auto |
auto, ask |
Never below the floor |
offer.accept |
seller agent | ask |
ask, auto |
Never below the floor |
deal.sign_contract |
— | forbid |
forbid |
Fixed (INV-3) |
account.update |
— | forbid |
forbid |
Fixed (INV-3) |
Category defaults for later verbs (handover.book_slot, deal.accept_deposit, passport.disclose_full_report)
carry over from [15.2] unchanged.
5.4 Offer budget
- The platform MUST count below-floor offers per buyer agent per listing, and MUST also apply a ceiling per buyer operator per listing of N times the per-agent budget. The platform publishes both numbers in discovery.
- Past either limit, every offer from that agent, or from that operator, on that listing gets 429
offer_budget_exhausteduntil the window frees a slot. Above-floor offers are included, so 201-versus-429 cannot reveal the floor. - An operator that rotates agent keys to dodge the per-agent budget still meets the operator ceiling, and breaches its partner terms [8].
6. Starter checkpoints and refunds (amends [7.3] and [16.2])
The Starter set becomes funds_held, accepted, rejected, return_received, released, refunded.
releasedrequiresfunds_heldand thenaccepted.rejectedcarries areason:not_as_describedornot_received.- After
rejectedwithnot_as_described,refundedrequiresreturn_received, written by the seller or a custodian. not_receivedis allowed only oncedeliver_within_days(from the term set) has passed sincefunds_held. After it,refundedneeds no return.- Any other order fails with 409
release_condition_unmet. - In Starter,
not_receivedrests on the buyer's word. Categories where that is too weak use the verified custody lane [6.4], where a courier signsdelivered.
7. Reason codes (amends [12])
| Change | Reason | HTTP | When |
|---|---|---|---|
| New | grant_invalid |
401 | The grant is unknown, or not bound to the signing key. Fix the integration. |
Renamed from mandate_revoked |
grant_revoked |
403 | The seller or operator revoked the grant. Ask the seller to reconnect. |
Renamed from mandate_expired |
grant_expired |
403 | The grant is past exp. Refresh or reconnect. |
| New | terms_invalid |
422 | Proposed terms break a term-set constraint |
| Narrowed | not_in_scope |
403 | The listing is not the grant's seller's, or has no terms |
All other Draft 0.3 reasons are unchanged.
8. Invariants
| ID | Draft 0.3 | Proposed |
|---|---|---|
| INV-1 | A refusal for a low offer says below_floor and never states the floor |
Private terms never leave the platform. No agent or counterparty receives them. A refusal says below_floor and may carry the seller's counter. |
| INV-2 | An ask that expires is a decline |
Unchanged |
| INV-3 | deal.sign_contract and account.update are always forbid |
Unchanged |
| INV-4 | Only the seller signs approvals | Unchanged |
| INV-5 | No agent input can change a tier, floor or budget; only a new mandate can | Only the seller, on a Trusted Surface, can create or change a grant or listing terms. No agent input can. |
| INV-6 | An accepted offer becomes a single-use, business-signed checkout | Unchanged |
| INV-7 | A revoked or expired mandate fails the next signed call | A revoked or expired grant fails the next signed call |
| INV-8 | No custom cryptography | Unchanged |
| INV-9 | No personal data in RCTP objects | Unchanged |
INV-1 moves from a promise about what the platform says to a property of who knows what: the seller agent cannot leak a floor it never received.
9. Resolution of the v0.1 ambiguities
Dissolved means the question no longer exists under this proposal. Resolved means the proposal states the answer as a rule.
| ID | Issue | Question | Status | Resolution | Section |
|---|---|---|---|---|---|
| A-1 | #2 | How does the enforcement point receive the mandate? | Dissolved | Nothing travels but a key-bound access token. The platform holds the grant and the terms. | 3.3 |
| A-2 | #3 | Is sending the mandate a presentation needing SD-JWT+KB? | Dissolved | No credential is presented to the enforcement point. Proof of possession is the RFC 9421 signature with keyid = cnf.jkt. Key-binding JWTs [3.2(1)] still apply to credentials agents present to each other [5, 6]. |
3.3 |
| A-3 | #4 | Which reason for an unverifiable mandate? | Resolved | grant_invalid (401) for unknown or unbound grants; grant_revoked, grant_expired (403). Each has one remedy. |
7 |
| A-4 | #5 | May a refusal's counter equal the floor? | Resolved | The term set requires counter gt_term: floor; such terms are refused terms_invalid before approval. The enforcement point still sends counter only when it is above the floor. |
4.3 |
| A-5 | #6 | After the budget is spent, do above-floor offers pass? | Resolved | No: every offer gets 429 until a slot frees. The budget is counted per buyer agent with an operator ceiling, so one abusive user no longer locks out a whole operator. | 5.4 |
| A-6 | #7 | Which action does an inbound offer evaluate? | Resolved | New verb offer.create, checked against the terms, with no tier. |
5.2, 5.3 |
| A-7 | #8 | Is a listing in scope by ID or category? What if it has no floor? | Dissolved | Scope is the seller's own listings that have terms. Every term set requires a floor, so a listing with terms always has one. | 4.6 |
| A-8 | #9 | Does the floor apply to the seller's own counter? | Resolved | Yes, and to listing.reprice as well. |
5.2, 4.4 |
| A-9 | #10 | Who may accept? | Resolved | Only the seller side, under offer.accept. A counter is an invitation; the buyer agrees by offer.create at that amount. |
5.2 |
| A-10 | #11 | Which reason for an approval response after expires_at? |
Resolved | The late response is refused approval_invalid; the approval is reported expired with approval_timeout; the action is declined (INV-2). |
[9.4] as clarified |
| A-11 | #12 | Status-list caching versus "the next call fails" | Dissolved | Grants are checked live; no status list is involved. Status lists stay for portable credentials, where the 60-second lifetime rule [3.3] applies. | 3.4 |
| A-12 | #13 | What must precede refunded? |
Resolved | rejected with a reason. not_as_described needs return_received first; not_received is allowed only after deliver_within_days. |
6 |
| A-13 | #14 | How is the seller's passkey registered? | Resolved | Out of RCTP's scope: the seller's existing marketplace account passkey is the approval key. The enrolment ticket stays a sandbox feature. | — |
| A-14 | #15 | No REST routes for checkout, checkpoints or fixed forbids | Resolved | Section 11 of the draft adds POST /deals (redeem a checkout), POST /deals/{id}/checkpoints and POST /listings/{id}/terms (opens a listing.set_terms approval). The always-refused routes stay test hooks in the binding, not the draft. |
[11] as amended |
10. Conformance
| Vector | Change |
|---|---|
| V1, V3, V7 | Floors come from Listing Terms instead of the mandate. Expectations unchanged. |
| V4 | Budget per buyer agent, plus a new case for the operator ceiling |
| V6 | A revoked grant fails the next signed call |
| V10 (new) | A listing the seller agent creates is negotiable as soon as the seller sets terms, with no new consent |
| V11 (new) | Private terms never reach any agent: listing data, decisions, approval request body, webhooks and attestation entries |
| V12 (new) | Terms with counter at or below floor are refused terms_invalid |
| V13 (new) | After rejected with not_as_described, refunded without return_received fails with release_condition_unmet |
11. Impact on the reference implementation
| Area | Change |
|---|---|
| Schemas | Remove mandate.seller.open.1. Add agent-grant, listing-terms, term-set. listing-create-request is unchanged; approval request display loses any price but the list price. |
| Registries | New term-sets. actions gains allowed_tiers, offer.create and listing.set_terms. Reason codes as in section 7. |
| Gateway (Go) | The mandate package shrinks to grant lookup. New terms store with salted commitments. Decision engine reads terms by listing. Hosted page renders the terms form from the term set. |
| Sandbox | The mock issuer becomes an authorization server that issues grants. The status list and SD-JWT minting for mandates go. |
| SDKs | SellerConnect returns a grant token; RctpClient sends Authorization and signs it. decodeMandate and verifyMandate are removed until credentials [5] arrive. |
| Docs | Quickstart, concepts, decisions and errors, security, partner profile. |
Net effect: less code. The credential, status-list and per-call mandate paths go; a terms store and one form come in.
12. Open questions for review
- Agent-suggested terms. May the seller agent propose a floor that pre-fills the form? It helps sellers price, but the agent would then know the suggested value, and sellers may anchor on it. Proposed: not in Draft 0.4.
- Default tier for
offer.accept.askis proposed. Isautowithin terms a sensible default for low-value categories? - First term sets.
goods.small/1andvehicles/1are proposed for Draft 0.4; property later. - Grant lifetime. At most 90 days with refresh is proposed. Should the platform also expire grants after a period of no use?
- Disclosure to the seller's own agent. Should a seller be able to opt in to their agent seeing the floor? Proposed: no. Negotiating blind costs the agent little, and it removes the leak path.
13. Revision: minimum core on UCP and AP2
Principle: simplicity is the ultimate complexity. RCTP defines the minimum a marketplace must implement and run.
Categories and logistics chains extend it through open values, not new protocol. Where UCP or AP2 already defines a verb
or noun, RCTP reuses it. Checked against UCP at commit f2626c2
(20 October 2026) and AP2 v0.2.
13.1 Reused, not redefined
| Need | Defined by | RCTP adds |
|---|---|---|
| Agent identity, request signing | UCP Signatures: UCP-Agent, keys in the /.well-known/ucp profile, RFC 9421 |
legal_entity and incident_contact in the profile |
| Seller's permission for an agent | UCP Identity Linking: OAuth 2.0 at the marketplace, scopes {capability}:{scope} with per-scope policy |
RCTP scopes; a tier (auto, ask) in each scope's policy; token bound to the agent key |
| Buyer questions | UCP Ask | Seller agent answers from structured facts only |
| Delivery method, carrier, windows, cost | UCP Fulfillment (open method types) | Nothing; marketplaces add types such as meetup or locker |
| When payment is due | UCP Payment Terms | Nothing |
| Paying into escrow | AP2 Payment Mandate: payment.allowed_payees |
Nothing; the payee is the holder of funds |
| Shipped, delivered, returned, refunded | UCP Order: fulfillment events and adjustments (open types) | Who signs each one (13.2) |
| Webhooks | UCP signed webhooks (Standard Webhooks headers, RFC 9421) | Nothing |
13.2 RCTP's core
Nothing in UCP or AP2 covers these:
- Offers.
dev.rctp.offer, a UCP checkout extension: create, counter, accept, decline. UCP has no negotiation; discussion #502 is open and invites vendor-namespaced prototypes. RCTP's offer is one. - Listing Terms (section 4).
- The decision:
auto,askorforbid, with one registered reason. - Signed proof. UCP order events are asserted by the business alone. RCTP attests who did what (
first_handby the carrier, holder or buyer agent;relayedby the marketplace) and which proofs release money. - Portable credentials: party bands, identity facts, item passport [5, 6]. UCP and AP2 do not describe the person or the item.
13.3 Fixed rules
Only these are fixed. Everything else is an open value named by reverse domain, as in UCP.
- The platform enforces the seller's terms, not the agent.
- No answer means no.
- Private terms never reach any agent.
- Money moves only on signed proof.
- Facts about people, never identities.
- No custom cryptography.
13.4 Review decisions
| Question | Decision |
|---|---|
| Is RCTP the place to book shipping? | No. RCTP covers proof and deal terms; booking, quotes and tracking stay in UCP Fulfillment and carrier APIs. |
| Who holds the buyer's money? | A role, not a company: the AP2 payee, either the marketplace or a licensed payment partner. It signs funds_held, release and refund. |
| When are carrier- or inspector-signed checks required? | Not in the core. An optional term in a category's term set, used by marketplaces that offer the category. |
| Can a seller require buyer identity or history? | Yes, as a requirement in Listing Terms. |
13.5 Changes to this proposal
- Deal Terms. An offer carries a price plus a fulfillment option (UCP Fulfillment) and a payment term (UCP Payment Terms) chosen from those the listing allows. The platform enforces the choice like the floor. The checkout binds all of it.
- Listing end date. Every term set gains
available_until. - Operator record, key directory,
RCTP-Operator: replaced by the UCP profile andUCP-Agent. - Agent Grant (section 3): a UCP Identity Linking grant with RCTP scopes; section 3.3 binding unchanged.
- Webhooks: UCP signed webhooks replace the RCTP format.
- Checkpoints (section 6): shipping, delivery, returns and refunds are UCP fulfillment events and adjustments,
attested by RCTP. RCTP keeps only
funds_held,accepted,rejectedandreleased. A refund afternot_as_describedneeds an attested, completedreturnadjustment. - UCP version is pinned in the binding.
- Sections 3, 6, 7, 10 and 11 are rewritten to match once the review adopts this section.
13.6 Open for review
- Draft 0.3 [9.2(4)] forbids refusing a buyer for having no trading history when the deal uses the verified custody lane. A fixed rule (13.3) or a recommended default?
- RCTP scope names, for example
dev.rctp.listing:create,dev.rctp.offer:counter,dev.rctp.offer:accept. - The UCP version to pin.
- When to propose
dev.rctp.offerto UCP discussion #502: after this review, or after v0.2 ships.
Source: spec/proposals/draft-0.4-listing-terms-and-agent-grants.md