Enruta

Docs · Objects

Reconciliation

LiveUpdated

Agents and Sellers. Written for people who build agents, the hosts they run in, and the people and companies the agents pay for and merchants that receive agent orders.

The three parties have no shared key: the mandate id lives with the agent, the order id with the merchant, the authorization id with the rail. Enruta writes the mandate id into every slot the others carry at issuance, then joins the five legs back into one line per mandate.

The line

FieldContents
id, mandate_id, record_id, periodrcl_…; the mandate is the root; period is the ISO week of issuance (2026-W37)
agent_legcredential_id, amount_mandated, payee_mandated, issued_at, agent_id, principal_login_id, policy_version
rail_auth_legrail, authorization_id, amount_authorized, merchant_descriptor, mcc, at, answered_in_ms
rail_settle_legtransaction_id, amount_settled, fees, settled_at, batch_id, finality_class
merchant_legprotocol, order_id, client_reference_id, amount_total, line_items_hash, catalog_snapshot_hash, order_confirmation_url, shipped, fulfilled_at, adjustments (the shipment and returns as the merchant reports them after the order)
adjustments_leg[]{ source: merchant_webhook | rail | enruta_reversal, kind, amount, at, reversal_id, reversal_record_id }
match_method, confidencekey_exact (the order’s checkout id equals the mandate’s, or the order carries the mandate id) 1.0 · rail_ref (only the authorization id links) 0.9 · heuristic (merchant name and amount ± 2 % inside 72 h) 0.6
match_statematched · partial · unmatched_agent (issued, never authorized) · unmatched_rail (a rail posting with no mandate) · unmatched_merchant (an order whose checkout matches no request)
exception_codes[], suggested_actions[]See below
human_outcomeWhat the person who approves decided, and the signing event
sealed, line_record_idSet when the report is signed and the line becomes a linked record

Exceptions

CodeMeaningSuggested action
AMOUNT_AUTH_NE_MANDATEThe rail authorized a different amount than the mandateCheck the rail’s limit semantics; the mandate account is the truth
AMOUNT_CLEARED_NE_AUTHThe rail cleared more or less than it authorizedA candidate reversal (initiator: enruta_policy, kind: chargeback_credit, status: requested) is created, not executed, and a dispute packet can be generated
PAYEE_MISMATCHThe merchant descriptor is not the mandated payeeReview the authorization and the merchant lock
DUPLICATE_RAIL_TXNTwo rail postings for one mandateQuery the rail
REFUND_UNMATCHEDA refund on the rail with no reversal or merchant adjustmentAsk the merchant; a rail-initiated reversal was created
ORDER_CONFIRMATION_MISSINGNo merchant order for a consumed mandatePoll the merchant’s order endpoint
RAIL_LIMIT_SEMANTICS_DIFFThe rail’s limit and the mandate account disagreeAdjust the rail-side limit tier
SETTLEMENT_OVERDUE24 hours past expected_settlement_at without a settled eventCheck the rail
FINALITY_MISMATCHThe settlement’s finality_class differs from the one stamped at issuanceReview the rail adapter

The three parties, one line

The $24.98 order of 2026-09-10 with the $9.99 refund of 2026-09-13:

SourceObjectAmountKey
Enrutamnd_01M2512M8FQ7ZK4T1V9W3N6BXC, credential ic_1S7Kq1…Ceiling $24.98Card metadata mandate = mnd_01M2512M…
Stripe Issuingiauth_1S7Kq2…, ipi_1S7Kq9…Authorized $24.98, cleared $24.98Same card
reamandrule.comord_01M2512SM3V3A9R4EBJM8RRRV5$24.98; adjustments: [{ refund 9.99 }]checkout_id = the mandate’s checkout reference
Stripe Issuingipi_1S7Rn4… (refund)−$9.99Linked to ipi_1S7Kq9…
{
  "id": "rcl_01M2GD4T7Q1W9K3N5B8H2D6XRS", "period": "2026-W37",
  "mandate_id": "mnd_01M2512M8FQ7ZK4T1V9W3N6BXC", "record_id": "rec_01M25129GZMJXTNQ47TMZRDGHN",
  "match_method": "key_exact", "confidence": 1.0, "match_state": "matched",
  "agent_leg": { "amount_mandated": "24.98", "payee_mandated": "reamandrule.com", "agent_id": "agt_procurement_02", "principal_login_id": "halvern/dana.reyes@halvernrobotics.com", "policy_version": 4 },
  "rail_auth_leg": { "rail": "stripe_issuing", "authorization_id": "iauth_1S7Kq2…", "amount_authorized": "24.98", "answered_in_ms": 44 },
  "rail_settle_leg": { "transaction_id": "ipi_1S7Kq9…", "amount_settled": "24.98", "finality_class": "reversible" },
  "merchant_leg": { "protocol": "ucp", "order_id": "ord_01M2512SM3V3A9R4EBJM8RRRV5", "amount_total": "24.98", "line_items_hash": "sha256:…" },
  "adjustments_leg": [
    { "source": "merchant_webhook", "kind": "refund", "amount": "9.99", "reversal_id": "rev_01M2G8YV5R3T7W2Q9K4N8B6DXP" },
    { "source": "rail", "kind": "refund", "amount": "9.99", "reversal_id": "rev_01M2G8YV5R3T7W2Q9K4N8B6DXP" }
  ],
  "exception_codes": [], "suggested_actions": [], "sealed": false
}

Had the rail cleared $27.48 (the merchant added shipping after authorization), the line would carry AMOUNT_CLEARED_NE_AUTH, a candidate chargeback_credit reversal, and the suggestion to generate a dispute packet.

The weekly report

FieldContents
id, periodrcr_…; one report per organization and ISO week
counts_by_match_stateHow many lines are matched, partial, unmatched
exceptions[]Every exception with its line, code and suggested action
coverage_pctmatched ÷ (all lines − unmatched_agent); the target is 99 % or better
line_ids[], root_hashThe lines, and a Merkle root over their JCS digests in id order
state, signed_by, signed_at, signaturedraftsigned; passkey (challenge = the 32 bytes of the root hash) or link key
report_record_idThe sealed linked record

Every Monday at 01:00 UTC the weekly job builds the draft for the previous week for every organization and emits reconciliation.report_ready; the finalize job rebuilds the lines of every mandate touched since its last run. Signing seals every line as a linked record (kind: reconciliation_line, chain: reconciliation_of the payment record) and then the report (kind: reconciliation_report, chain: report_for, agent: null, the signature as approval: a passkey makes it third_party_signed, a link customer_attested). What was signed is what the auditor re-runs.

Interfaces

SurfaceCallWho
RESTGET /v0/reconciliation/lines?period=&state=, GET /v0/reconciliation/lines/{mandate_id}, GET /v0/reconciliation/reports/{period}, POST …/reports/{period}/build, POST …/reports/{period}/sign (link key)Developer; auditor reads
REST, sellersGET /v0/sellers/reconciliation?period=, the seller’s slice by orderSeller key
MCPget_reconciliation({ mandate_id }), get_reconciliation({ period })The agent, read-only
SDKreconciliation.lines(q), .line(mandateId), .report(period), .buildReport(period), .signReport(period)
CLIenruta reconciliation lines [--period 2026-W37], enruta reconciliation report 2026-W37 [--build] [--sign]
Console/reconciliation: period picker, lines with match-state chips and exception codes, the report card, “Build report”, “Sign with passkey”Owner, approver

How the person who approves reads and signs it: Weekly report.