Specification
About the specDraft 0.5v0.3 bindingAmbiguitiesSpec changelogRe-Commerce Trust Profile — Specification (Draft 0.3)
Oct 10, 2026 · @Kelvin Vuong
Status and abstract
This is Draft 0.3 of the Re-Commerce Trust Profile (RCTP), for internal review. It is not stable; every name, field and number may change. The companion white paper explains why; this document says what an implementation must do.
Changes since Draft 0.2:
- Seller and buyer sections in the Counterparty Credential, with three new buyer bands (5.1).
- An identity facts module that a government e-ID service or eKYC provider can issue without adopting the rest of RCTP, with assurance levels and per-country issuer trust lists (5.4).
- Contact and delivery details disclosed only by lane and deal stage (5.5).
- Owner and return-match checks as item attestations (6.2).
- Custody checkpoints in the Transaction Attestation, each marked first-hand or relayed, mapped to GS1 EPCIS step names (7.3).
- Obligations for partner operators whose assistants act for sellers (8).
- AP2 Intent and Cart Mandates recognised as the buyer's permission (9.3).
- An approval interface, so a partner's app can show an approval while only the seller's own key signs it (9.4).
- A Starter profile naming the attestations to build first (16.2), plus new reason codes, threats, registries, vectors and examples.
Draft 0.2 added verified custody, buyer agent defaults, credential hardening, the consumer-reporting check and the two-implementation rule for Draft 1.0.
RCTP is a profile of existing standards for agent-to-agent trade in used goods. It defines four objects (Seller Mandate, Counterparty Credential, Item Passport, Transaction Attestation), an identity facts module that public e-ID services can issue, one adopted record (Operator record), the decisions an enforcement point makes, the defaults a buyer agent follows, an approval interface, a verified custody lane with signed checkpoints, and the UCP capabilities that carry offers, item facts and staged deals. It defines no new cryptography, transport or payment rail.
Placeholder names: this draft uses the reserved documentation domain rctp.example. Capability names therefore read example.rctp.*, and extension URIs begin https://rctp.example/. All will move to a neutral registered domain before Draft 1.0.
Governance: the editors intend to move the specification to a neutral home, such as a foundation that already hosts agent protocols, before any outside implementer is asked to depend on it.
1. Conventions and terminology
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 and RFC 8174) when, and only when, they appear in all capitals.
| Term | Meaning |
|---|---|
| Holder | The person a credential describes, acting through their own agent |
| Seller agent | Software acting for a seller under a Seller Mandate |
| Buyer agent | Software acting for a buyer, such as a general-purpose assistant |
| Enforcement point | A gateway or library in front of a marketplace API that evaluates mandates on every call |
| Issuer | A party that signs Seller Mandates or Counterparty Credentials, usually a marketplace identity service |
| Identity issuer | A public e-ID service or licensed eKYC provider that signs identity facts (5.4) |
| Attester | A party that signs facts about one item, such as a registry, inspection centre or notary |
| Custodian | A party that holds an item, or inspects it at pickup or delivery, and signs what it checked |
| Protected payment | Payment held by a third party and released only when a stated condition holds |
| Funds held | A signed entry from the holder of funds stating that the buyer's payment is held for this deal |
| Verified custody lane | A deal in which a Custodian checks the item and protected payment is released when the buyer accepts it (6.4) |
| First-hand, relayed | Whether the party signing an entry observed the event itself, or is passing on a named partner's report |
| Identity facts | Minimal facts about a person, such as "verified person" or "over 18", with no name or identity number |
| Tier | One of auto (act without asking), ask (act only after human approval) or forbid (never act) |
| Band | A coarse range that replaces a raw number, such as 50-200 completed trades |
| Trusted Surface | A screen the human controls where consent and approvals are given, as in AP2 |
| Approval surface | Where a seller sees and answers an ask: the marketplace's app, a marketplace page inside a partner's app, or a certified partner's own screen (9.4) |
| Deal | A multi-stage transaction whose stage changes are signed and may move money |
| Pairwise pseudonym | An identifier for one party that is unique to one relationship or one deal, so it cannot be joined across them |
2. Roles
RCTP names roles, never companies. One organisation MAY play several roles; each role's duties apply in full regardless.
| Role | MUST | MUST NOT | Maps to |
|---|---|---|---|
| Issuer | Publish type metadata, band methodology and status lists; issue only after holder consent; have the methodology independently reviewed each year | Learn which verifier checked which credential; refuse issuance because a holder trades elsewhere | AP2 root SD-JWT issuer |
| Identity issuer | Sign only identity facts it verified; publish its key in its country's trust list | Sign reputation, names, identity numbers or addresses | SD-JWT VC issuer of person identification data, as in EU digital identity wallets |
| Holder agent | Present its own credentials directly to the counterparty; keep a local presentation log | Present a credential bound to someone else's key | AP2 Shopping Agent or the new seller-agent role |
| Buyer agent | Default to protected payment; act within the buyer's AP2 mandates; tell its principal which item facts are attested before paying | Pay off-platform, pass payment links, or move a deal to an outside channel without an explicit ask |
AP2 Shopping Agent |
| Verifier | Check signature, key binding, type and status locally; request only the section of a credential that fits the holder's role | Call the issuer per presentation; forward disclosed claims to any issuer | Any agent receiving a presentation |
| Enforcement point | Evaluate every seller-agent action and inbound offer against the Seller Mandate; verify approvals; write attestation entries | Let a model, prompt or agent override a tier | UCP Business endpoint |
| Attester | Sign only facts it checked; publish liability terms | Attest facts outside its stated competence | SD-JWT issuer for item facts |
| Custodian | Inspect before signing; bind each attestation to the listing and the item; record seals; publish liability terms and pay what they promise | Release goods or funds before the release condition holds | SD-JWT issuer for item facts; UCP fulfillment provider |
| Approval surface | Show the exact action, amount and counterparty bands; return the seller's own signature over the approval challenge (9.4) | Approve on timeout; sign with an operator key | AP2 Trusted Surface |
3. Common rules
All RCTP credentials are SD-JWT VCs, all requests are signed with HTTP Message Signatures, and all status is checked against shared lists.
3.1 Credential format
- Issuers MUST encode Seller Mandates, Counterparty Credentials and Item Passport attestations as SD-JWT VCs per draft-ietf-oauth-sd-jwt-vc, using the SD-JWT format of RFC 9901.
- The
typheader MUST bedc+sd-jwt. - Every credential MUST carry
vct,iss,iat,exp,cnfandstatus.vctvalues are registered in section 15. - Issuers MUST publish SD-JWT VC type metadata for each
vct, including the band methodology URL for Counterparty Credentials.
3.2 Key binding and request signing
- Every credential MUST be bound to a holder key through
cnf. Presentations MUST include a key-binding JWT (SD-JWT+KB) whoseaudis the verifier and whosenoncethe verifier supplied. - Holder keys SHOULD be generated in hardware-backed storage on the holder's device and SHOULD NOT be exportable. For deals above a value the verifier sets, a presentation SHOULD carry a fresh user-verification proof from a platform authenticator, such as a passkey assertion, so a lent or stolen credential cannot be used without its holder present.
- Every agent request to an enforcement point MUST be signed per RFC 9421. Keys MUST be discoverable through the operator's key directory (section 8).
3.3 Status lists
- Revocation MUST use the Token Status List mechanism (draft-ietf-oauth-status-list).
- An issuer MUST place each credential in a list shared with many others. It MUST NOT create a list per holder or per credential.
- Verifiers SHOULD fetch whole lists and cache them for the list's stated lifetime. Seller Mandate lists SHOULD have a short lifetime so revocation takes effect within minutes (proposed: 60 seconds).
3.4 Bands
Numeric facts about people MUST be expressed as bands from the registered vocabularies (section 15.3), never as raw numbers.
3.5 Names and versions
Capability names use the reverse-domain form example.rctp.<name>, following UCP's namespace rules. Each vct ends in a version number; a breaking change MUST increment it. Verifiers MUST reject a vct version they do not support.
4. Seller Mandate
A Seller Mandate (vct = mandate.seller.open.1) is an open mandate in AP2's sense: bound to one agent key, valid for many actions until it expires or is revoked. Each action it governs produces a closed record as a Transaction Attestation entry.
4.1 Claims
| Claim | Required | Content |
|---|---|---|
accountable_human |
Yes | Issuer-internal party reference, identity assurance, consent screen version, consent time |
agent |
Yes | agent_id, operator_id, key_directory |
inventory_scope |
Yes | Marketplace, listing IDs or listing hashes, categories, exclusions |
commercial |
Yes | Currency, price_floor per listing, optional preset_counter per listing, reprice_band |
actions |
Yes | Map of registered action name to tier |
ask |
Yes | approval_surfaces allowed (9.4), with an amount cap for certified_operator; timeout_seconds; on_timeout is always deny |
offer_budget |
Yes | Maximum below-floor offers per buyer operator per listing, and the window |
counterparty_requirements |
No | Minimum buyer-section bands and identity assurance a buyer's credential must show before an offer reaches the seller, outside the verified custody lane |
handover_windows |
No | Days, hours and places the seller accepts for viewings and inspections |
settlement_requirements |
No | Whether escrow or the verified custody lane (6.4) is required; deposit percentage |
4.2 Processing rules
- The issuer MUST issue a mandate only after the human confirms it on a Trusted Surface showing every tier, floor and exclusion in plain language.
- An enforcement point MUST treat any action not listed in
actionsasforbid. deal.sign_contractandaccount.updateMUST beforbid. An issuer MUST NOT issue a mandate that maps either to another tier.- A floor check overrides the tier: an accept below
price_floorisforbideven when the accept action isauto. - The mandate and its
accountable_humanclaim MUST NOT be shown to counterparties. Only the enforcement point and the holder's agent see it. - A revoked or expired mandate MUST cause the next signed call to fail with
mandate_revokedormandate_expired.
5. Counterparty Credential
A Counterparty 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. In person-to-person trade each side carries risk from the other, so both sections matter. The holder's agent presents it directly to the other side; the issuer is never contacted per presentation.
5.1 Selectively disclosable claims
| Claim | Section | Values |
|---|---|---|
identity_assurance |
Common | Level (phone_only, document_check, bank_kyc, gov_eid), source and first_hand or relayed (5.4) |
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 | Upheld complaints against the buyer, such as false "not as described" claims, swapped returns or payment reversals: 0, 1, 2-plus, insufficient-history |
buyer.no_show_band |
Buyer | Share of confirmed viewings or handovers missed without cancelling: lt-5pct, 5-20pct, 20pct-plus, insufficient-history |
5.2 Issuance
- The credential MUST NOT contain
subor any stable identifier of the holder. - Issuers SHOULD issue credentials in batches, each with its own
cnfkey and salts. Holder agents SHOULD use each credential for one presentation only. seller.dispute_rate_bandMUST beinsufficient-historybelow a minimum number of completed sales, stated in the methodology. Buyer bands follow the same rule for purchases.- The band methodology MUST be published. It SHOULD weight each completed trade by the strength of the counterparty's own credential, and MUST NOT count trades between accounts the issuer links to one person.
- Issuers MUST let holders view their bands and the inputs behind them, and contest them.
- An issuer also gains when its own traders sell, so it MUST have the methodology and its application reviewed by an independent party at least once a year, and MUST publish the review's attestation URL in the type metadata. Verifiers MAY decline credentials from issuers without a current review.
- Buyer bands MUST count only events the issuer was party to. A complaint against a buyer counts only once upheld through a dispute process the buyer could answer. A no-show counts only against a booking both sides confirmed, and never when the buyer cancelled within the window the deal allowed or the seller did not attend.
5.3 Presentation and verification
- A verifier MUST request only the claims it needs and MUST supply a fresh
nonce. - The holder's agent MUST disclose no more than requested. It MAY disclose fewer, and the verifier then decides.
- The verifier MUST check the issuer signature, key binding,
vct,expand status locally. It MUST NOT call the issuer per presentation. - A verifier MAY accept credentials only from issuers on a trust list it chooses. The profile defines no single root of trust.
- A verifier MUST request only the section that fits the holder's role in this deal: common and buyer claims from a buyer, common and seller claims from a seller.
5.4 Identity facts module
Identity facts are the part of a person's trust that a public e-ID service can vouch for. They form a small, separate profile (vct = credential.identity.1) that a government e-ID service or a licensed eKYC provider can issue without implementing the rest of RCTP. A Counterparty Credential carries their summary in identity_assurance.
| 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 business registration, for professional sellers |
licensed_trade |
Licence type and issuing authority, for dealers and agents |
assurance |
Level (phone_only, document_check, bank_kyc, gov_eid), source service, and first_hand or relayed |
- An identity issuer MUST sign only facts it verified. It MUST NOT sign reputation, trade history or dispute outcomes; those belong to marketplace issuers, because only they saw the trades.
- Names, identity numbers, dates of birth and addresses MUST NOT appear as claims. Derived facts such as
age_over_18are used instead. - When a marketplace re-signs facts a public e-ID service confirmed to it, each fact MUST be marked
relayed, with the source service and confirmation time. The marketplace MUST keep the source response for audit and MUST NOT forward it. The holder's consent MUST cover presentation to counterparties, and the source service's terms MUST permit it. - When a public e-ID service issues the credential itself into the holder's wallet, the facts are
first_handand verifiers check them against that service's published key. - Accepted identity issuer keys are published per country in an open trust list (15.3). A verifier MAY require
first_handfacts or a minimumassurancelevel for high-value deals.
Illustrative sources, subject to each service's terms: Singpass Myinfo in Singapore, VNeID in Vietnam, MyDigital ID in Malaysia and iAM Smart in Hong Kong. In Vietnam, the accounts of e-commerce sellers must be linked to and verified with VNeID by 31 December 2026.
5.5 Contact and delivery details
Knowing the other side does not require knowing who they are. Contact details are disclosed only when a deal needs them.
- In the verified custody lane, the buyer's delivery address goes only to the Custodian or courier, and the seller's pickup address only to the courier. Neither party receives the other's address or phone number.
- For meetups, viewings, test drives and property, names and phone numbers are disclosed only after both sides confirm a handover slot through
example.rctp.handover. - Before that, each side sees only the other's disclosed bands and identity assurance.
- Delivery and contact details travel in UCP checkout and fulfillment objects to the marketplace, which passes them on under these rules. Agents MUST NOT relay them between the parties.
6. Item Passport
An Item Passport is a set of attestations about one unique item, each an SD-JWT VC (vct = passport.item.1) signed by the attester that checked the fact. The seller's agent holds them and discloses each at the stage the seller chose.
6.1 Attestation claims
| Claim | Content |
|---|---|
item_ref |
A salted digest of the item identifier (VIN, IMEI, title number), never the raw identifier before the disclosure stage allows it |
attestation_type |
A registered type (table 6.2) |
result |
The finding, in the vocabulary of that type |
observed_at, valid_until |
When the attester checked, and until when it stands behind the finding |
details |
Selectively disclosable specifics, such as an odometer reading or a land area |
liability_terms |
URL of the attester's published liability terms |
6.2 Initial attestation types
| Type | Category | Disclosed before deposit |
|---|---|---|
registration_match |
Auto | Match yes or no, model, year |
periodic_inspection |
Auto | Valid-until date, odometer |
lien_free |
Auto, Real Estate | Yes or no |
inspection_report |
Auto | Grade and summary; full report after deposit |
title_verified |
Real Estate | Yes or no, area, land-use type |
ownership_or_poa |
Real Estate | Yes or no; identity after deposit |
owner_match |
Auto, Real Estate | The seller is the registered owner: yes or no, and the source registry |
planning_zone |
Real Estate | Summary |
grade_certificate |
Collectibles | Grading company, grade, certificate number |
custody_verified |
Any item that can ship | Checks performed, result, seal reference |
handover_inspection |
Any item that can ship | Accepted or rejected at delivery, reason code |
return_match |
Any item that can ship | The returned item matches the seal and identifier recorded at pickup: yes or no |
authenticity_check |
Collectibles, luxury goods, phones | Method (human, lab or model), result, examiner or model version |
device_clean |
Phones and electronics | Identifier not on a block list, not locked to another account, battery health band |
6.2.1 Example sources by market
The types are market-neutral; each market supplies its own attesters. The examples below are illustrative, and each market's issuers and document names need legal confirmation before a pilot.
| Type | Singapore | Australia | United States | Japan | Vietnam |
|---|---|---|---|---|---|
registration_match |
LTA vehicle registration | State road agency registration | State certificate of title | Vehicle inspection certificate (shakenshō) | Vehicle registration certificate |
periodic_inspection |
LTA periodic inspection | Roadworthy certificate; in Victoria, issued within 30 days of a private sale | State safety or emissions inspection, where required | Shaken inspection | Periodic inspection (đăng kiểm) |
lien_free |
Finance company or credit bureau check | PPSR search | Liens recorded on the state title | To confirm | Secured-transaction registration |
title_verified |
Singapore Land Authority title search | State land titles registry | Title company search and title insurance | Real property registry | Land-use and ownership certificate (sổ đỏ, sổ hồng) |
owner_match |
Vehicle and property records shared through Myinfo, to confirm for marketplace use | To confirm | State title records | To confirm | Vehicle and land records through VNeID's planned document integration, to confirm |
custody_verified |
Marketplace checkpoint (planned) | To confirm | Authentication services that hold an item before shipping it on | Grading company for cards; to confirm for other goods | Planned on Chợ Tốt's existing held payment (Thanh Toán Đảm Bảo), adding inspection on delivery |
Canada's provinces keep personal property registries that can serve as lien_free attesters in the same way as Australia's PPSR.
6.3 Rules
- Each attestation MUST include a
disclose_athint:listing,reserveordeposit. The seller's mandate decides the tier for disclosing anything abovelisting. - Listing facts and passport facts MUST be structured claims. Seller agents MUST answer buyer questions from these claims, not from free-text descriptions, to limit prompt injection.
- An attester MUST be able to revoke an attestation through its status list when it learns the finding was wrong.
- An
authenticity_checkMUST state its method (human,labormodel) and the examiner or model version. Amodelresult on its own MUST use a screening result (screening_pass,screening_failorinconclusive), neverauthentic, unless the attester's liability terms cover a wrong call.
6.4 Verified custody
In the verified custody lane, a Custodian checks the item, the buyer's money is held, and the money moves only when the buyer accepts the item. The lane lets two strangers trade safely when neither has a trading history.
- A Custodian MUST inspect the item either on receipt at a checkpoint or at pickup by a courier, and sign a
custody_verifiedattestation bound to the listing hash, theitem_refand the SHA-256 of its inspection photos. - Payment MUST be held under
example.rctp.escrowwith a release condition ofbuyer_acceptedorhandover_inspection_passed. Funds MUST NOT reach the seller before that condition holds, and MUST be refunded to the buyer if the buyer rejects the item within the dispute window for a registered reason. - The buyer, or a courier for the buyer, MAY inspect at delivery. The result is a
handover_inspectionattestation signed by the courier and countersigned by the buyer's agent. - A Custodian's liability terms MUST state what it pays if its attestation proves wrong. A Custodian that pays out for its own wrong attestation MUST also revoke that attestation.
- Custody does not replace the Seller Mandate.
order.commit_to_shipkeeps its tier, and the floor rules of 4.2 still apply. - Each custody step (received, inspected, sealed, dispatched, delivered, accepted or rejected, released or refunded) MUST be written to the Transaction Attestation by the party that performed it.
The first deployment is planned in Vietnam, where held payment and inspection on delivery already operate; other markets follow once their checkpoint partners and payment licences are confirmed.
7. Transaction Attestation
A Transaction Attestation (vct = attestation.transaction.1) is the dispute record for one deal: a hash-chained list of entries, each signed by the party that wrote it. No party needs another's signature for its own entries to count.
7.1 Entries
| Field | Content |
|---|---|
deal_id |
Identifier unique to this deal |
seq, prev_hash |
Position in the chain and the SHA-256 of the previous entry |
t |
Time of the event |
author |
Pairwise pseudonym of the writing party for this deal, or the enforcement point's identifier |
action, tier, result |
The registered action, the tier applied, and the outcome |
checkpoint |
For custody events, the registered checkpoint type (7.3) |
observation |
first_hand if the author observed the event; relayed if it passes on a partner's report |
reported_by, source_event_id |
For relayed entries: the reporting partner and its own event identifier |
evidence |
SHA-256 digests of photos, one-time codes, seal references or documents; the evidence itself is shared only in a dispute |
approval |
For ask tiers: the approval ID, the approval surface used, the time, and the digest of the text shown (9.4) |
mandate_ref |
jti and SHA-256 of the Seller Mandate in force |
ap2_refs |
SHA-256 of AP2 closed mandates and receipts for the same deal |
countersignatures |
Optional signatures of other parties over the entry |
7.2 Rules
- The enforcement point MUST write an entry for every decision it makes, including refusals.
- Entries MUST NOT record a floor value. A refusal entry records
below_floorand the offered amount only. - Each party MAY add entries and countersignatures. A refusal to countersign MUST NOT invalidate the entry.
- Either party MAY submit the bundle to an arbiter when a dispute is opened. The arbiter MUST use it for that case only and delete it after the stated retention period.
- A holder MAY submit the bundle to its own issuer to update its bands. Issuers MUST NOT require or solicit submission from counterparties, and MUST accept a bundle only if the enforcement point's entries verify.
- An entry reporting an event the author did not observe MUST be marked
relayedand MUST name the reporting party and its event identifier. A relayed entry asserts that the report was received, not that the event happened. - Entries MUST NOT contain addresses, phone numbers, personal names or the names of courier staff. Locations are given at city level, and photos and documents are referenced by digest.
7.3 Custody checkpoints
Only checkpoints that move money or responsibility are recorded. In-transit scans stay in the logistics provider's tracking. Status updates travel as UCP order and fulfillment events; the entry adds the signature, the observation marking and who is liable. Step names map to GS1 EPCIS so logistics partners need no new vocabulary.
| Checkpoint | Written by | What it unlocks | EPCIS step |
|---|---|---|---|
funds_held |
Holder of funds | The seller may commit to ship | — |
picked_up_sealed |
Courier or Custodian, with the seal reference | Custody and liability pass to the courier | shipping |
custody_inspected |
Custodian | The custody_verified attestation (6.4) |
inspecting |
delivered |
Courier, with a one-time code or photo digest | The buyer's acceptance window starts | receiving |
accepted, rejected |
Buyer's agent | Release or refund | accepting |
return_received |
Seller or Custodian, with a return_match check |
Refund | receiving |
lost_or_damaged |
Courier | An insurance or liability claim | — |
released, refunded |
Holder of funds | The deal closes | — |
- A marketplace that relays a partner's checkpoints MUST have partner terms that make the partner liable for its own reports.
- The seal reference and item identifier recorded at
picked_up_sealedMUST be compared atdeliveredand atreturn_received. A mismatch MUST block release or refund withseal_mismatchuntil resolved. - A seller sees the buyer's payment only as a
funds_heldentry signed by the holder of funds, never as a screenshot or a payment link passed between the parties.
8. Operator record
The Operator record names who runs an agent and who answers when it misbehaves. Know Your Agent has no published schema yet, so RCTP defines a minimal record and will map it once one appears.
| Field | Required | Content |
|---|---|---|
operator_id |
Yes | Stable identifier of the operator |
legal_entity, jurisdiction |
Yes | The accountable company and its country |
incident_contact, incident_sla_hours |
Yes | Where to report misuse and how fast the operator responds |
key_directory |
Yes | URL of the operator's HTTP Message Signatures key directory |
agents |
Yes | Agent identifiers and archetypes (buyer-agent, seller-agent) |
certifications |
No | Schemes the operator is assessed against, with dates |
data_residency, key_custody |
No | Where agent data and signing keys are held |
- The operator MUST sign the record and publish it at a stable URL referenced from its agents' requests.
- Enforcement points MUST refuse calls from an agent whose operator record cannot be resolved or whose key is not in the directory.
- Operators SHOULD publish
data_residencyandkey_custodywhen they act across borders. - An operator whose agents act for sellers MUST NOT export buyer data, contact buyers outside the marketplace, or use RCTP data for advertising, and MUST state these limits in its partner terms with each marketplace.
- An operator whose own app acts as an approval surface MUST list the certification for the
certified_operatorlevel incertifications, and is limited to the amount cap each mandate sets (9.4).
9. Enforcement decisions
The enforcement point, not the agent, decides every action. It returns one of three decisions in a Mandate-Decision response header, defined as a Structured Field (RFC 9651) Token with parameters.
Figure — Enforcement decision: five checks, then the tier. A signed call arrives. (1) Signature and operator valid? No → 401
signature_invalidoroperator_unknown. (2) Mandate current and unrevoked? No → 403mandate_revokedormandate_expired. (3) Action allowed and in scope? No → 403action_forbiddenornot_in_scope. (4) Buyer bands meet requirements? No → 403counterparty_requirements_unmet. (5) Offer at or above the floor? No → 403below_floor, with the preset counter; 429 once the offer budget is spent. (6) Which tier does the mandate set?auto→ 200, the action completes;ask→ 202, one push to the seller, no answer means no. Every decision, including each refusal, writes a signed attestation entry (section 7).
Checks run in this order so the cheapest refusals come first. The floor check sits after the counterparty check, so a buyer who fails the bands never learns how close their offer was.
| Decision | HTTP status | Parameters | Meaning |
|---|---|---|---|
auto |
200 | none | Done |
ask |
202 | approval_id, expires_in, on_timeout=deny; the body carries the approval request (9.4) |
Waiting for the human; no answer means no |
forbid |
403 | action, reason, optional counter |
Refused on the seller's own terms |
forbid |
429 | reason=offer_budget_exhausted, retry_after |
Too many below-floor offers from this buyer operator |
9.1 Rules
- A
forbidfor a low offer MUST usereason=below_floorand MUST NOT state the floor. It MAY carrycounter, the seller's preset counter price. - The enforcement point MUST count below-floor offers per buyer operator per listing. Past the mandate's
offer_budget, it MUST answer 429 until the window resets. - An
askMUST reach the human only through an approval surface the mandate allows, and MUST be decided only by the seller's own signature (9.4). The outcome reaches the caller by a signed webhook or by polling. - If
counterparty_requirementsare set, the enforcement point MUST verify the buyer's presentation before the offer reaches the seller, and refuse withcounterparty_requirements_unmetif bands fall short. - An accepted offer MUST become a business-signed checkout bound to the listing hash, offer ID, price, buyer agent key thumbprint, expiry and a single-use nonce. A second use MUST fail with
offer_replayed. - No input from an agent, prompt or listing text can change a tier or a floor. Only a new mandate from the issuer can.
9.2 Buyer agent defaults
Most marketplace fraud happens when a buyer pays a stranger outside the platform. These defaults make the protected path the normal one, so a credential system protects buyers rather than only labelling safe sellers.
- A conformant buyer agent MUST, by default, pay for second-hand goods only through protected payment: the verified custody lane (6.4) or escrow with a release condition (10.2).
- A buyer agent MUST NOT pay a counterparty directly, or move a conversation to an outside messaging channel, when a protected path exists for that listing. It MAY do so only after an explicit
askon its principal's Trusted Surface that states the purchase is unprotected. - Before payment, a buyer agent MUST tell its principal which item facts are attested and by whom, and which are only the seller's own claims.
- An enforcement point MUST NOT refuse a buyer only because its bands show
insufficient-historyor0completed trades when the deal uses the verified custody lane.counterparty_requirementsapply only outside that lane. - A principal MAY change these defaults, but only on a Trusted Surface, never through the agent.
9.3 Buyer authority
RCTP defines no buyer mandate. AP2 already gives the buyer a permission slip, and RCTP uses it.
- An enforcement point MUST accept a valid AP2 Intent or Cart Mandate as proof that a buyer agent may make an offer or a purchase, and MUST refuse an offer above that mandate's amount limit with
buyer_authority_exceeded. - The buyer's identity facts and buyer bands come from the buyer's own credential (5), presented in-band through
example.rctp.counterparty. - Payment authority comes from AP2's Payment Mandate. Under the buyer defaults (9.2), it SHOULD carry
payment.release_condition(10.2). - Agents MUST NOT pass payment links or payment instructions between the parties. The seller learns that the buyer has paid only from a
funds_heldentry (7.3).
9.4 Approval interface
When an action needs the seller's yes, a partner's app can show the approval, but only a key the seller controls can sign it. Where an approval is shown and who signs it are separate.
| Level | Shown in | Signed with | Allowed when |
|---|---|---|---|
marketplace_app |
The marketplace's app, with a matching short code shown in the partner's chat | The seller's passkey with the marketplace | Any amount |
hosted_embedded |
An approval panel hosted by the marketplace, opened inside the partner's app | The seller's passkey with the marketplace | Any amount; the recommended default for partner apps |
certified_operator |
The partner's own interface | A hardware-backed approval key on the seller's device that needs biometrics or a PIN, registered with the marketplace when the seller connected the partner | Only for operators certified for this level, and only below the amount cap in the mandate |
The approval request travels in the body of a 202 ask decision. It contains the approval_id, the action, the listing hash, the amount and currency, the counterparty's disclosed bands, display (the exact text to show, per language), expires_at, a one-time challenge bound to all of these and expressed as RFC 9396 authorization details, the levels the mandate allows, and the hosted approval URL.
The approval response contains the approval_id, decision (approve or decline), the signature over the challenge (a WebAuthn assertion at the first two levels), the level used, and the SHA-256 of the text actually shown.
- Before acting, the enforcement point MUST verify that the signature comes from the seller's registered key, answers this challenge, is within
expires_at, is used for the first time, and uses a level the mandate allows. Otherwise it refuses withapproval_invalidorapproval_surface_not_allowed. - No reply by
expires_atis a decline. deal.sign_contract, account changes, and any amount above the certified cap MUST usemarketplace_apporhosted_embedded.- The approval, its level and the displayed-text digest are written to the Transaction Attestation (7.1).
- A
marketplace_appapproval MAY be requested through OpenID CIBA. Browser flows MAY use W3C Secure Payment Confirmation where it is supported.
10. UCP capabilities and extensions
RCTP ships its commerce pieces as UCP capabilities in its own namespace, as UCP's contribution process asks of new capabilities. Where UCP work is already open on a concern, RCTP composes with it and will migrate if that work lands.
| Name | Kind | Extends | Adds | Composes with |
|---|---|---|---|---|
example.rctp.listing |
Extension | dev.ucp.shopping.catalog.search, .catalog.lookup |
Unique item, quantity 1, condition grade, listing hash | — |
example.rctp.passport |
Extension | listing, checkout |
Passport summaries and staged disclosure | — |
example.rctp.counterparty |
Extension | offer, checkout |
In-band credential presentation and nonce exchange | — |
example.rctp.offer |
Root capability | — | Offer, counter, accept, decline, expire, with the decision on every response | Discussion #502; issue #845 for the accepted-offer handoff |
example.rctp.handover |
Extension | dev.ucp.shopping.fulfillment |
Methods: viewing, test_drive, inspection, notarized_transfer, courier_with_inspection, custody_checkpoint; required attendees |
Slots and holds of the proposed Local Services council |
example.rctp.deal |
Root capability | — | Staged deal: reserve, inspect, deposit, finance, transfer, release | Lifecycle modelled on UCP lodging bookings |
example.rctp.escrow |
Extension | checkout, deal |
Holder of funds, release conditions (including buyer_accepted and handover_inspection_passed), dispute window, refund path |
UCP payment terms; Payments council work on conditional capture |
10.1 Offer states
open → countered or requires_escalation → accepted, declined, expired or refused. An offer in requires_escalation carries expires_at and becomes expired when the ask times out.
10.2 AP2 constraint proposal
payment.release_condition restricts an open Payment Mandate to pay only into a named escrow account, released on a named condition. Credential providers check it the way they check amount limits today. It is proposed to FIDO, not defined here.
11. Transport bindings
One JSON Schema per operation is the source of truth; the REST, MCP and A2A bindings MUST be generated from it, not written by hand. The decision semantics are identical on every transport.
| Operation | REST | MCP tool | Decision carried in |
|---|---|---|---|
| Create offer | POST /offers |
create_offer |
Mandate-Decision header; structuredContent.decision |
| Get offer | GET /offers/{id} |
get_offer |
Offer status |
| Counter offer | POST /offers/{id}/counter |
counter_offer |
As above |
| Accept offer | POST /offers/{id}/accept |
accept_offer |
As above; returns the signed checkout on success |
| Decline offer | POST /offers/{id}/decline |
decline_offer |
As above |
| Request presentation | POST /presentations/requests |
request_presentation |
Returns the nonce and the claims requested |
| Present credential | POST /presentations |
present_credential |
Verification result |
| Book handover slot | POST /deals/{id}/handover |
book_handover |
As above |
- REST. Requests MUST be signed per RFC 9421 and carry the agent's operator reference.
- MCP. Operations run as
tools/call; RCTP metadata travels inparams.argumentsand results inresult.structuredContent, as UCP's MCP binding does. Aforbidis returned as a tool error with the registered reason. - A2A. The extension URI is
https://rctp.example/a2a/v1, and its specification MUST be hosted at that URI. Clients activate it with theA2A-Extensionsheader, following A2A's extension mechanism.
12. Error and reason codes
Every refusal carries exactly one registered reason, so the calling agent can act on it without a human reading a message.
| Reason | HTTP | When |
|---|---|---|
below_floor |
403 | Offer or accept under the seller's floor; the floor is never stated |
offer_budget_exhausted |
429 | Too many below-floor offers from this buyer operator in the window |
action_forbidden |
403 | The action is forbid or not listed in the mandate |
not_in_scope |
403 | The listing or category is outside inventory_scope |
counterparty_requirements_unmet |
403 | The buyer's presented bands fall short, outside the verified custody lane |
buyer_authority_exceeded |
403 | The offer or purchase exceeds the buyer's AP2 mandate limit |
protected_payment_required |
403 | The mandate or the buyer's defaults require the verified custody lane or escrow |
release_condition_unmet |
409 | Funds were requested before the release condition holds |
seal_mismatch |
409 | The seal or item identifier at delivery or return does not match pickup |
custody_attestation_invalid |
422 | A custody or handover attestation does not bind to this listing or item |
approval_invalid |
403 | An approval's signature, challenge, expiry or single use does not verify |
approval_surface_not_allowed |
403 | The approval came through a level the mandate does not allow, or above the certified cap |
approval_timeout |
403 | An ask expired with no answer |
mandate_revoked |
403 | The mandate's status entry is revoked |
mandate_expired |
403 | The mandate is past exp |
offer_expired |
409 | The offer passed expires_at |
offer_replayed |
409 | An accepted offer's nonce was already used |
signature_invalid |
401 | The RFC 9421 signature or key binding failed |
operator_unknown |
401 | The operator record or key directory could not be resolved |
13. Security considerations
The threat RCTP is built around is a well-behaved agent making a bad decision. Each threat below has a control in the spec, and each control has a conformance vector (section 16).
| Threat | Control | Section |
|---|---|---|
| An agent is persuaded or injected into a bad deal | Tiers and floors enforced outside the model; structured listing facts | 4.2, 6.3, 9.1 |
| A buyer binary-searches the floor | No floor in refusals or attestations; per-operator offer budgets | 7.2, 9.1 |
| An accepted offer is replayed or altered | Business-signed checkout, single-use nonce, listing hash binding | 9.1 |
| A stolen agent key keeps acting | Short-lived mandate status lists; revocation fails the next call | 3.3, 4.2 |
| Fake approvals | Approvals decided only by the seller's own signature over a one-time challenge | 9.4 |
| A partner app shows one thing while the seller signs another | Challenge bound to the action and amount; displayed-text digest recorded; partner-rendered approvals only when certified and below a cap | 9.4 |
| Farmed reputation | Weighted, published methodology; linked accounts excluded; yearly independent review | 5.2 |
| A credential is lent, sold or stolen | Device-bound holder keys; fresh user verification for larger deals; verifier fraud reports | 3.2, 14 |
| A scammer moves the deal off-platform | Buyer agents default to protected payment and refuse outside channels without an explicit ask |
9.2 |
| Fake payment screenshots or phishing payment links aimed at sellers | Sellers see payment only as a signed funds_held entry; agents never pass payment links |
7.3, 9.3 |
| "You sent me a brick" claims and swapped returns | Seal and identifier compared at pickup, delivery and return; return_match check |
6.2, 7.3 |
| Buyer no-shows at viewings and handovers | Buyer no-show band; optional booking deposit | 5.1 |
| A wrong item attestation | Attester liability terms and revocation; dispute window in the deal | 6.1, 6.3 |
| A counterfeit passes a model check | Method and version stated; a model result alone is screening, not authentication; Custodian liability | 6.3, 6.4 |
| A relayed checkpoint is wrong | Relayed entries name their source; partner terms carry the liability | 7.2, 7.3 |
| Government identity data is over-shared | Derived facts only; no names or identity numbers; the source response is kept for audit and never forwarded | 5.4 |
| Funds released before the buyer accepts | Release conditions enforced by the funds holder; payment mandates restricted to escrow | 6.4, 10.2 |
| Agents bypass the enforcement point by scraping | Marketplaces block unsigned automation; signed calls are the only agent path | 8 |
| A compromised enforcement point | Its entries are signed and chained; holders and arbiters can audit them | 7.2 |
Marketplace APIs MUST enforce OAuth scopes before any of this holds. A mandate in front of an API that ignores scopes is a promise, not a control.
14. Privacy considerations
An issuer learns only from events it is party to. The seven channels below are the complete list; anything else an issuer learns about a trade is non-conformant.
| Channel | Rule |
|---|---|
| 1. Check | Issuers MUST NOT receive any per-presentation signal. Status lists MUST be shared (3.3). |
| 2. Refresh | Issuers MAY see the holder's own refresh requests, and MUST NOT ask why they are made. |
| 3. Settlement | Issuers MAY receive a bundle only when the holder submits it. Counterparties appear as pairwise pseudonyms. |
| 4. Dispute | Arbiters MAY receive a bundle when a party opens a dispute, for that case only, with a stated retention period. |
| 5. Fraud | Verifiers MAY report one credential with evidence. The holder MUST be notified and MUST be able to appeal. |
| 6. Aggregates | Verifiers MAY opt in to contribute counts with differential privacy through a separate aggregator. Results MUST be published to every member. |
| 7. Billing | Paid verification MUST be metered per verifier, not per holder, for example with Privacy Pass tokens (RFC 9576–9578). |
- Issuers MUST NOT expose a credential lookup keyed by a person or account identifier.
- Issuers MUST NOT change bands, fees or ranking because a holder presented a credential elsewhere or traded on another marketplace.
- No party may use RCTP data for advertising or targeting.
- Buyer agents' customer data (identity, searches, baskets) MUST NOT be sent to any issuer.
- Holder agents SHOULD keep a local log of every presentation and show it to the holder.
- Bands are automated profiling with significant effects, so holders need paths to access, correct and object. Implementers MUST meet each market's data protection law, for example Singapore's PDPA, which gives individuals the right to request access to and correction of their personal data, or Vietnam's Personal Data Protection Law, in force since 1 January 2026, and equivalent laws in Australia, Japan, Canada and the United States.
- Before issuing credentials that verifiers in a market will rely on, an issuer MUST obtain legal advice on whether its credentials are regulated there as consumer reports. In the United States, for example, the Fair Credit Reporting Act's definition of a consumer report covers information bearing on a person's general reputation.
- No RCTP object carries addresses, phone numbers, identity numbers or personal names. Identity facts are derived (5.4), and contact and delivery details follow 5.5.
15. Registries
Twelve registries live as versioned files in the specification repository. Additions need editor review; removals need a new major version. Tiers in 15.2 are category defaults; each Seller Mandate sets its own, except where Fixed says otherwise.
15.1 Credential types (vct)
mandate.seller.open.1 · credential.counterparty.1 · credential.identity.1 · passport.item.1 · attestation.transaction.1
15.2 Actions
| Action | Phones and small goods | Auto | Real Estate | Fixed |
|---|---|---|---|---|
listing.answer_buyer |
auto |
auto |
auto |
— |
listing.reprice |
auto |
ask |
ask |
— |
offer.counter |
auto |
auto |
ask |
— |
offer.accept |
ask |
ask |
ask |
Never below floor |
handover.book_slot |
— | auto |
auto |
— |
passport.disclose_full_report |
— | ask |
ask |
— |
deal.accept_deposit |
— | ask |
ask |
— |
deal.sign_contract |
— | forbid |
forbid |
Always forbid |
order.commit_to_ship |
ask |
— | — | — |
listing.create |
ask |
ask |
ask |
Never outside inventory_scope |
account.update |
forbid |
forbid |
forbid |
Always forbid |
15.3 Other registries
- Band vocabularies: the common, seller and buyer values in section 5.1.
- Identity assurance levels:
phone_only,document_check,bank_kyc,gov_eid, each markedfirst_handorrelayed(5.4). - Identity issuer trust lists: accepted identity issuer keys, one open list per country (5.4).
- Attestation types: the values in section 6.2.
- Authenticity methods:
human,lab,model. - Handover methods:
viewing,test_drive,inspection,notarized_transfer,courier_with_inspection,custody_checkpoint. - Release conditions:
buyer_accepted,handover_inspection_passed. - Custody checkpoints: the values in section 7.3, with their EPCIS step names.
- Approval levels:
marketplace_app,hosted_embedded,certified_operator(9.4). - Reason codes: the values in section 12.
16. Conformance
An implementation conforms to a role at a level only by passing that level's published test vectors. Each vector records the correct result and the plausible wrong answers a reasonable implementation might give, as the UCP Local Services charter does for its own vectors.
| Level | Covers | Roles tested |
|---|---|---|
| Core | Seller Mandate and enforcement decisions | Issuer, enforcement point, seller agent |
| Approval | The approval interface at each level an implementation claims | Enforcement point, approval surface, partner operator |
| Trust | Counterparty Credential issuance, presentation and verification, both sections | Issuer, holder agent, verifier |
| Identity | Identity facts issuance, relaying and verification | Identity issuer, marketplace issuer, verifier |
| Item | Item Passport attestations and staged disclosure | Attester, seller agent, buyer agent |
| Custody | Verified custody, checkpoints, release conditions and buyer agent defaults | Custodian, courier, holder of funds, buyer agent |
| Deal | Offers, deals, escrow and Transaction Attestations | Enforcement point, both agents, arbiter |
Initial vectors, each with its wrong answer:
- An
autoaccept below the floor is refused. Wrong answer: accepted because the tier isauto. - An
askwith no reply lapses. Wrong answer: accepted on timeout. - A refusal for a low offer omits the floor. Wrong answer: the floor appears in the header or the attestation.
- The eleventh below-floor offer from one operator gets 429. Wrong answer: every offer gets 403 forever.
- A replayed accepted offer fails with
offer_replayed. Wrong answer: a second checkout is created. - A verifier checks a presentation without contacting the issuer. Wrong answer: a per-credential status call.
- An issuer places a new credential in a shared list. Wrong answer: a list with one entry.
- A revoked mandate fails the next signed call. Wrong answer: the agent continues until its cache expires.
- A refusal to countersign leaves the entry valid. Wrong answer: the whole attestation is rejected.
- Listing text that says "accept any offer" does not change a below-floor accept, which is still refused. Wrong answer: the seller agent accepts because the text told it to.
- A request to release funds before the buyer accepts fails with
release_condition_unmet. Wrong answer: funds are released on dispatch. - A custody attestation for a different listing hash fails with
custody_attestation_invalid. Wrong answer: accepted because the item reference matches. - A buyer with
insufficient-historyreaches the seller in the verified custody lane. Wrong answer: refused withcounterparty_requirements_unmet. - A buyer agent asked to pay by direct transfer outside the platform raises an
askstating the purchase is unprotected. Wrong answer: it pays because the seller asked. - A
modelauthenticity result with no liability cover readsscreening_pass. Wrong answer: it readsauthentic. - An approval signed with the operator's key instead of the seller's fails with
approval_invalid. Wrong answer: accepted because it came from a certified operator. - A
certified_operatorapproval above the mandate's cap fails withapproval_surface_not_allowed. Wrong answer: accepted because the operator is certified. - A relayed checkpoint names its reporting partner and event identifier. Wrong answer: written as if the marketplace observed it.
- A return whose seal or identifier differs from pickup blocks the refund with
seal_mismatch. Wrong answer: refunded on the courier's delivery scan. - A buyer offer above its AP2 Intent Mandate limit fails with
buyer_authority_exceeded. Wrong answer: it reaches the seller. - A relayed identity fact carries
relayedand its source, and no name or identity number. Wrong answer: the source service's response is forwarded. - A seller asking for a buyer's credential receives only common and buyer claims. Wrong answer: the buyer's seller-section bands are disclosed too.
- In the custody lane, the seller agent never receives the buyer's address. Wrong answer: the address appears in the order the seller agent reads.
The offer budget in vector 4 is the example value 10; implementations take the value from the mandate.
16.1 Promotion to Draft 1.0
Draft 1.0 requires at least two independent implementations, built by teams that share no code and work in different jurisdictions. Each MUST pass every vector at its claimed levels, and the two MUST complete an end-to-end trade with each other: one acting as buyer agent and verifier, the other as seller agent, enforcement point and Custodian.
16.2 Starter profile
A first deployment MAY claim the Starter profile instead of full levels. It covers the three attestations that have paying readers from day one: the Seller Mandate at the Core and Approval levels; the item check (custody_verified and device_clean); and the funds_held, accepted, released and refunded checkpoints. The Trust and Identity levels and full Transaction Attestation bundles are added when an outside verifier, partner or arbiter asks for them.
17. References
Normative
- BCP 14: RFC 2119 and RFC 8174, requirement key words
- RFC 9901, Selective Disclosure for JWTs (SD-JWT)
- draft-ietf-oauth-sd-jwt-vc, SD-JWT-based Verifiable Digital Credentials
- draft-ietf-oauth-status-list, Token Status List
- RFC 9421, HTTP Message Signatures
- RFC 9651, Structured Field Values for HTTP
- RFC 9396, OAuth 2.0 Rich Authorization Requests
- OpenID Connect Client-Initiated Backchannel Authentication (CIBA) Core 1.0
- W3C Web Authentication (WebAuthn) Level 3
- UCP specification, release v2026-08-25
- AP2 v0.2
- A2A extensions
Informative
- RFC 9576, RFC 9577 and RFC 9578, Privacy Pass
- W3C Secure Payment Confirmation
- GS1 EPCIS 2.0 and Core Business Vocabulary 2.0
- UCP contribution process · discussion #502 · issue #845 · issue #922
- Know Your Agent collaboration
- Chợ Tốt held payment (Thanh Toán Đảm Bảo) announcement
- Vietnam: accounts that must be linked to VNeID by 31 December 2026
- A trusted agent protocol for peer-to-peer trade, group brief, Revision 3
- Re-Commerce Trust Profile white paper, Draft 0.2
Appendix A. Example records and exchanges
These are illustrative shapes, not shipped records. Identifiers, amounts and URLs are invented; .example domains are placeholders.
A.1 Seller Mandate (decoded payload)
{
"vct": "mandate.seller.open.1",
"iss": "https://id.marketplace.example",
"iat": 1791590400, "exp": 1794182400,
"jti": "mnd_01K8Y3VH2PQ4R7",
"cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." } },
"accountable_human": { "party_ref": "internal-only", "identity_assurance": "gov_eid", "consent_screen_version": "v0.3" },
"agent": { "agent_id": "agt:seller:7c1f", "operator_id": "op:example-seller-agents", "key_directory": "https://agents.example/.well-known/http-message-signatures-directory" },
"inventory_scope": { "marketplace": "marketplace.example", "listing_ids": ["118829301"], "categories": ["mobile-phones"], "excludes": ["luxury"] },
"commercial": { "currency": "SGD", "price_floor": { "118829301": 420.00 }, "preset_counter": { "118829301": 430.00 }, "reprice_band": { "max_markdown_pct": 12, "min_interval_hours": 24 } },
"actions": { "listing.create": "ask", "listing.answer_buyer": "auto", "listing.reprice": "auto", "offer.counter": "auto", "offer.accept": "ask", "deal.sign_contract": "forbid", "account.update": "forbid" },
"ask": {
"approval_surfaces": ["marketplace_app", "hosted_embedded", { "certified_operator": "op:example-seller-agents", "max_amount": 200.00 }],
"timeout_seconds": 900, "on_timeout": "deny"
},
"offer_budget": { "below_floor_max": 10, "window_hours": 24 },
"status": { "status_list": { "uri": "https://id.marketplace.example/status/mandates-2026-10", "idx": 40219 } }
}
A.2 Counterparty Credential presentation (a buyer's disclosed claims)
{
"vct": "credential.counterparty.1",
"iss": "https://id.marketplace.example",
"disclosed": {
"identity_assurance": { "level": "gov_eid", "source": "VNeID", "observation": "relayed" },
"buyer.completed_purchases_band": "10-49",
"buyer.adverse_findings_band": "0",
"buyer.no_show_band": "lt-5pct"
},
"kb_jwt": { "aud": "op:example-seller-agents", "nonce": "n-5f2c", "iat": 1791612483 }
}
No subject identifier and no recipient field travel with the credential. The holder's agent logs the presentation locally.
A.3 Item Passport attestation (decoded payload)
{
"vct": "passport.item.1",
"iss": "https://inspection.example",
"item_ref": "sha-256:3b9e...",
"attestation_type": "periodic_inspection",
"result": "valid",
"observed_at": "2026-09-30", "valid_until": "2027-03-30",
"details": { "odometer_km": 48210 },
"disclose_at": "listing",
"liability_terms": "https://inspection.example/terms"
}
A.4 Transaction Attestation entries
[
{ "seq": 1, "t": "2026-10-10T00:03:51Z", "author": "ep:marketplace.example", "action": "offer.accept", "tier": "forbid", "result": "below_floor", "offered": 360.00, "prev_hash": "sha-256:0000..." },
{ "seq": 2, "t": "2026-10-10T14:20:09Z", "author": "ep:marketplace.example", "action": "offer.accept", "tier": "ask", "result": "approved",
"approval": { "id": "apr_01K8ZB7", "level": "hosted_embedded", "at": "2026-10-10T14:22:40Z", "displayed_text": "sha-256:4be1..." },
"mandate_ref": { "jti": "mnd_01K8Y3VH2PQ4R7", "hash": "sha-256:9f2a..." }, "prev_hash": "sha-256:1c80..." },
{ "seq": 3, "t": "2026-10-10T14:31:02Z", "author": "pay:holder.example", "checkpoint": "funds_held", "observation": "first_hand", "prev_hash": "sha-256:7a11..." },
{ "seq": 4, "t": "2026-10-11T02:15:44Z", "author": "ep:marketplace.example", "checkpoint": "picked_up_sealed", "observation": "relayed",
"reported_by": "courier.example", "source_event_id": "evt-55821", "location": "Ho Chi Minh City",
"evidence": { "seal_ref": "seal-88213", "photos": ["sha-256:aa01..."] }, "prev_hash": "sha-256:b3c9..." }
]
A.5 Decision headers
HTTP/1.1 202 Accepted
Mandate-Decision: ask; approval_id="apr_01K8ZB7"; expires_in=900; on_timeout=deny
HTTP/1.1 403 Forbidden
Mandate-Decision: forbid; action="offer.accept"; reason=below_floor; counter=430.00
HTTP/1.1 429 Too Many Requests
Mandate-Decision: forbid; reason=offer_budget_exhausted; retry_after=3600
A.6 Custody attestation (decoded payload)
{
"vct": "passport.item.1",
"iss": "https://custody.marketplace.example",
"item_ref": "sha-256:7d1a...",
"attestation_type": "custody_verified",
"result": "pass",
"observed_at": "2026-10-12T03:10:00Z", "valid_until": "2026-10-26",
"details": {
"listing_hash": "sha-256:c41e...",
"checks": ["device_clean", "authenticity_check"],
"photos": ["sha-256:aa01...", "sha-256:aa02..."],
"seal_ref": "seal-88213"
},
"disclose_at": "listing",
"liability_terms": "https://custody.marketplace.example/terms"
}
A.7 Approval request and response
{
"approval_request": {
"approval_id": "apr_01K8ZB7",
"action": "offer.accept",
"listing_hash": "sha-256:c41e...",
"amount": { "value": 9200000, "currency": "VND" },
"counterparty": { "buyer.completed_purchases_band": "10-49", "buyer.adverse_findings_band": "0" },
"display": { "vi": "Chấp nhận 9.200.000 ₫ cho iPhone 13?", "en": "Accept 9,200,000 VND for iPhone 13?" },
"expires_at": "2026-10-10T14:37:40Z",
"challenge": "b64url:Q2xh...",
"allowed_levels": ["marketplace_app", "hosted_embedded"],
"hosted_url": "https://approve.marketplace.example/apr_01K8ZB7"
},
"approval_response": {
"approval_id": "apr_01K8ZB7",
"decision": "approve",
"level": "hosted_embedded",
"assertion": "webauthn:...",
"displayed_text": "sha-256:4be1..."
}
}
A.8 Identity facts, relayed from a public e-ID service (decoded payload)
{
"vct": "credential.identity.1",
"iss": "https://id.marketplace.example",
"verified_person": true,
"age_over_18": true,
"residency_country": "SG",
"assurance": { "level": "gov_eid", "source": "Singpass Myinfo", "observation": "relayed", "confirmed_at": "2026-10-09T08:00:00Z" },
"cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." } }
}
No name, identity number or date of birth appears; the marketplace keeps the source response for audit and never forwards it.
Source: spec/rctp-draft-0.3.md