RPP402-005: Settlement
| RFC | RPP402-005 |
| Title | Settlement |
| Status | Draft |
| Version | 1.0.0 |
| Requires | RPP402-004 |
Overview
Settlement is the execution of an authorized Payment Intent as an onchain transaction on Robinhood Chain. It is where RPP402 stops being an off-chain coordination protocol and becomes a set of asset transfers with finality. A Settlement always references exactly one Payment Intent and produces exactly one Receipt (RPP402-006).
Motivation
Everything before Settlement (Discovery, Quote, Session, Intent) is coordination -agreement between agent and Service about what will happen. Settlement is where it actually happens, on a chain neither party can unilaterally rewrite. Splitting "agreed" (Intent) from "happened" (Settlement) into two primitives, rather than collapsing them the way a single 402 cycle does, is what lets a Session hold multiple legs safely: every leg's payment is authorized together (one Intent per asset) but the chain interaction that finalizes it is its own auditable step.
Problem
Settlement has to handle two asset paths differently (stablecoin vs. tokenized security, per RPP402-004), has to be idempotent (a retried Settlement request must not double-spend), and has to expose enough onchain detail that a Receipt (RPP402-006) can be independently verified without trusting the Service's word for it.
Terminology
| Term | Definition |
|---|---|
| Settlement | The settle_ object defined below. |
| Asset transfer | One onchain transfer within a Settlement -a Settlement covering a multi-leg Session with several recipients may contain several transfers in one transaction. |
| Finality | The point after which a confirmed Settlement cannot be reorganized away -see Security. |
Protocol
Settlement is initiated automatically by the Service once a Payment Intent reaches authorized; there is no separate "start settlement" call an agent makes manually beyond authorizing the Intent. A Settlement object is created and its status tracked, readable at GET {endpoints.session}/{id}/settlement (see RPP402-003 §Endpoints) once it exists:
| Field | Type | Description |
|---|---|---|
rpp402_version | string | "1.0". |
id | string | settle_ prefixed. |
intent_id | string | The Payment Intent this executes. |
session_id | string | Denormalized from the Intent for convenience. |
chain_id | string | "robinhood-1". |
tx_hash | string | null | Set once submitted onchain. |
block_number | integer | null | Set once included in a block. |
status | string | pending → submitted → confirmed | failed. |
transfers | array<Transfer> | One per leg's recipient; see below. |
reference_price | ReferencePrice | null | Present only when the Intent's asset is tokenized_security with amount_mode: "notional_usd" -see RPP402-004. |
created_at | string (RFC 3339) | |
confirmed_at | string (RFC 3339) | null |
Transfer:
{ "from": "0xaaaa...1234", "to": "0x1111...aaaa", "asset": { "...": "AssetRef" }, "amount": "0.002" }ReferencePrice (notional-mode tokenized-security settlements only):
{ "oracle": "robinhood-chain-price-oracle", "symbol": "NVDA.rh", "price_usd": "132.50", "sourced_at": "2026-07-10T18:24:03Z" }Asset-specific settlement paths
- Stablecoin: a direct token transfer per leg recipient, batched into one transaction when the Intent covers multiple legs in the same asset.
- Tokenized security: transfer of the security token contract, with
fixed_quantityexecuting directly andnotional_usdfirst resolvingamount / reference_price.price_usdinto a token quantity, then transferring that quantity. For agents settling viaagentic_account_delegation(RPP402-004), the transfer additionally releases the corresponding collateral hold on the Agentic Account rather than moving from a plain wallet balance.
Settlement submission is idempotent on intent_id: resubmitting a Settlement request for an Intent that already has a non-failed Settlement returns the existing object rather than creating a second one.
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://rpp402.com/schemas/v1/settlement.json",
"title": "RPP402 Settlement",
"type": "object",
"required": ["rpp402_version", "id", "intent_id", "session_id", "chain_id", "status", "transfers", "created_at"],
"properties": {
"rpp402_version": { "type": "string", "const": "1.0" },
"id": { "type": "string", "pattern": "^settle_[a-zA-Z0-9]{8,}$" },
"intent_id": { "type": "string", "pattern": "^intent_[a-zA-Z0-9]{8,}$" },
"session_id": { "type": "string", "pattern": "^sess_[a-zA-Z0-9]{8,}$" },
"chain_id": { "type": "string" },
"tx_hash": { "type": ["string", "null"], "pattern": "^0x[a-fA-F0-9]{64}$" },
"block_number": { "type": ["integer", "null"] },
"status": { "type": "string", "enum": ["pending", "submitted", "confirmed", "failed"] },
"transfers": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["from", "to", "asset", "amount"],
"properties": {
"from": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" },
"to": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" },
"asset": { "$ref": "https://rpp402.com/schemas/v1/asset-ref.json" },
"amount": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]+)?$" }
}
}
},
"reference_price": {
"type": ["object", "null"],
"properties": {
"oracle": { "type": "string" },
"symbol": { "type": "string" },
"price_usd": { "type": "string" },
"sourced_at": { "type": "string", "format": "date-time" }
}
},
"created_at": { "type": "string", "format": "date-time" },
"confirmed_at": { "type": ["string", "null"], "format": "date-time" }
}
}Examples
{
"rpp402_version": "1.0",
"id": "settle_c91a4f",
"intent_id": "intent_9a1b02",
"session_id": "sess_9a1b02",
"chain_id": "robinhood-1",
"tx_hash": "0x7e2f...c9a1",
"block_number": 4821093,
"status": "confirmed",
"transfers": [
{
"from": "0xaaaa...1234",
"to": "0x2222...bbbb",
"asset": { "type": "tokenized_security", "symbol": "NVDA.rh", "chain_id": "robinhood-1", "contract": "0x2222...bbbb", "issuer": "Robinhood Assets (Jersey) Limited" },
"amount": "0.3773"
}
],
"reference_price": { "oracle": "robinhood-chain-price-oracle", "symbol": "NVDA.rh", "price_usd": "132.50", "sourced_at": "2026-07-10T18:24:03Z" },
"created_at": "2026-07-10T18:24:01Z",
"confirmed_at": "2026-07-10T18:24:03Z"
}(0.3773 ≈ 50.00 / 132.50, matching the notional-mode Intent example in RPP402-004.)
Security
- A Settlement MUST NOT submit onchain if the referenced Intent's
statusis anything other thanauthorized, or if the Intent'sexpires_athas passed. - Finality follows Robinhood Chain's own finality guarantees (Arbitrum-Orbit L2, ~100ms blocks with L1 finality lagging behind); a Settlement's
statusonly moves toconfirmedafter the block is final by the chain's own rules, not merely included. reference_priceMUST be sourced from the same oracle a corresponding Receipt (RPP402-006) discloses -an agent or auditor must be able to independently re-check the conversion after the fact, not just trust the Service's arithmetic.- Idempotency (above) is itself a security property: without it, a network retry of a Settlement submission could otherwise be misread as agent intent to pay twice.
Errors
type | status | Meaning |
|---|---|---|
https://rpp402.com/errors/intent-not-authorized | 409 | Intent isn't authorized. |
https://rpp402.com/errors/intent-expired | 410 | |
https://rpp402.com/errors/settlement-failed | 502 | Onchain transaction reverted or failed to confirm; see status: "failed" object for detail. A failed Settlement requires a new Session -Sessions are not reopened (see RPP402-003). |
https://rpp402.com/errors/insufficient-balance | 402 | Payer's balance (or Agentic Account collateral) is insufficient at execution time. |
Best Practices
- Treat
status: "submitted"as provisional; only"confirmed"is safe to treat as final for accounting purposes. - For notional-mode tokenized-security settlements, always persist
reference_pricealongside the Settlement in any downstream system -it's the only record of what conversion actually happened. - Don't retry a failed Settlement's Intent; start a new Session. The Intent that failed is bound to the Session's leg set at the moment it failed and cannot be safely reused.
Reference Implementation
Schema: -packages/protocolsettlement.schema.json (Phase 4, this phase). Onchain execution: (tracked alongside Phase 4/5). Client: packages/contractssession.settle() in @rpp402/sdk (Phase 5).
Previous: RPP402-004 -Payment Intent · Next: RPP402-006 -Receipt
