Skip to main content
This guide walks through a complete tokenised repo lifecycle - from opening to maturity to closing - using paired instructions and autonomous on-chain execution.

Prerequisites

  • Authenticated with M2M token (Authentication)
  • A DvP settlement template available
  • Both parties have wallet addresses on a supported chain
  • You know the repo economics: tenor, rate, and haircut

Flow overview

A repo consists of two linked settlements:
  1. Opening: Both parties submit repo_open instructions for the same pre-agreed repo; when they agree, the opening settlement is created
  2. Closing: KeyStone auto-creates a repo_close settlement when maturity arrives
Both settlements follow the standard flow: instruction confirmation, compliance, deposits to escrow, autonomous execution.

Step 1: Submit opening instructions

Both counterparties submit instructions with trade_type: "repo_open" and identical repo_terms. The first party receives a trade reference, the second party includes it to complete the pair. Seller submits first:
Response includes a trade_reference:
Buyer submits with the same trade_reference:
When both instructions are confirmed, the response shows status: "matched" and includes the settlement_id.
timeout_at controls when the opening settlement times out if not completed. Maturity is derived, not passed: the closing settlement is due tenor_days after the opening settlement is created. The closing repayment is also derived - each closing payment leg accrues interest against its own opening quantity via tenor_days and rate_bps - so you never pass it explicitly. Quantities are integer base units, and the derived repayment floors to a base unit.

Step 2: Repo-specific instruction fields

Step 3: Opening settlement processes

The confirmed instructions create a settlement with:
  • trade_type: "repo_open"
  • repo_terms stored on the settlement
  • Standard DvP flow: compliance screening, escrow deposits, atomic execution
The settlement engine processes it automatically through all stages.

Step 4: Await maturity

The opening settlement finalizes. KeyStone derives the maturity as the opening settlement’s creation time plus tenor_days and checks it on a schedule. When maturity arrives, the system automatically creates the closing settlement - provided every party environment is active. A deactivated environment accepts no new settlements, so the closing is derived on the first check after reactivation instead; maturity does not expire.

Triggering maturity early (admin only)

Administrators can trigger maturity before the scheduled date:

Step 5: Closing settlement auto-created

At maturity, KeyStone auto-creates the closing instructions (each opening leg mirrored: whoever received an asset returns it) - no party action is required to create it. The closing settlement then goes through the full flow: compliance re-screening, deposits to escrow, autonomous execution.
  • Mirrored legs: Each opening leg comes back with its two sides swapped - whoever received an asset delivers it back, to whoever delivered it. Parties keep the roles they held on the opening
  • Repayment amount: Each closing payment leg is derived from tenor_days, rate_bps, and its own opening quantity (principal + interest per leg), floored to an integer base unit
  • Linked: linked_settlement_id ties the closing settlement to its opening (and repo_terms.close_leg_settlement_id on the opening points forward)

Step 6: Closing settlement completes

The closing settlement follows the same standard DvP flow:
  1. Compliance screening
  2. Escrow deposits (buyer deposits bonds, seller deposits USDC with interest)
  3. Atomic execution (bonds return to seller, USDC + interest returns to buyer)
  4. Settlement finalizes
Your webhook endpoint receives settlement.state.finalized for the closing settlement. At any point, you can query both legs of a repo:
Response:
(Both objects are full settlement resources; only the repo-relevant fields are shown here. Calling /related on either leg returns the same pair.) A session token restricted with settlement_ids must list both legs to read the pair: /related authorizes every settlement it returns, and a token scoped to one leg gets 403 SESSION_SETTLEMENT_SCOPE_DENIED once the other leg exists.

Error scenarios

See Webhooks for setup instructions.