> ## Documentation Index
> Fetch the complete documentation index at: https://docs.keystoneos.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Your First Settlement

> End-to-end walkthrough of a complete DvP settlement lifecycle.

This guide walks through the complete lifecycle of a Delivery vs. Payment (DvP) settlement, from instruction submission to autonomous on-chain finalization.

## What we are building

A tokenized private credit settlement where:

* **Seller** delivers 100 tokens of a private credit fund
* **Buyer** pays 50,000 USDC
* Both legs settle atomically - either both complete or neither does

## 1. Browse available templates

Templates define the settlement workflow and are pre-configured by KeyStone. Browse the available templates to find the right one for your use case.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.keystoneos.xyz/v1/settlement-templates \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```typescript TypeScript SDK theme={null}
  const { items } = await client.templates.list();

  for (const template of items) {
    console.log(`${template.slug} - ${template.name}`);
  }
  ```

  ```python Python SDK theme={null}
  result = await client.templates.list()

  for template in result.items:
      print(f"{template.slug} - {template.name}")
  ```
</CodeGroup>

Pick the template that matches your settlement type. For a standard DvP settlement, use the `dvp-standard` template. Note the `slug` field - you will reference it when submitting instructions.

<Note>
  Templates are managed by KeyStone admins. If you need a custom template for your use case, contact your KeyStone representative.
</Note>

## 2. Submit the seller instruction

The seller's platform submits their side of the trade:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.keystoneos.xyz/v1/instructions \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "idempotency_key": "my-first-dvp-seller",
      "template_slug": "dvp-standard",
      "role": "seller",
      "party": {
        "external_reference": "seller-001",
        "name": "Acme Securities",
        "wallet_address": "0xSellerWallet..."
      },
      "legs": [
        {
          "leg_type": "asset_delivery",
          "instrument_id": "0xTokenAddress",
          "quantity": "100",
          "direction": "deliver",
          "chain_id": 11155111
        },
        {
          "leg_type": "payment",
          "instrument_id": "0xUSDCAddress",
          "quantity": "50000",
          "direction": "receive",
          "chain_id": 11155111
        }
      ],
      "timeout_at": "2026-03-17T00:00:00Z"
    }'
  ```

  ```typescript TypeScript SDK theme={null}
  const sellerInstruction = await client.instructions.submit({
    idempotencyKey: client.generateIdempotencyKey(),
    templateSlug: "dvp-standard",
    role: "seller",
    party: {
      externalReference: "seller-001",
      name: "Acme Securities",
      walletAddress: "0xSellerWallet...",
    },
    legs: [
      { legType: "asset_delivery", instrumentId: "0xTokenAddress", quantity: "100", direction: "deliver", chainId: 11155111 },
      { legType: "payment", instrumentId: "0xUSDCAddress", quantity: "50000", direction: "receive", chainId: 11155111 },
    ],
    timeoutAt: "2026-03-17T00:00:00Z",
  });

  const tradeReference = sellerInstruction.tradeReference;
  ```

  ```python Python SDK theme={null}
  seller_instruction = await client.instructions.submit({
      "idempotency_key": "my-first-dvp-seller",
      "template_slug": "dvp-standard",
      "role": "seller",
      "party": {
          "external_reference": "seller-001",
          "name": "Acme Securities",
          "wallet_address": "0xSellerWallet...",
      },
      "legs": [
          {"leg_type": "asset_delivery", "instrument_id": "0xTokenAddress", "quantity": "100", "direction": "deliver", "chain_id": 11155111},
          {"leg_type": "payment", "instrument_id": "0xUSDCAddress", "quantity": "50000", "direction": "receive", "chain_id": 11155111},
      ],
      "timeout_at": "2026-03-17T00:00:00Z",
  })

  trade_reference = seller_instruction.trade_reference
  ```
</CodeGroup>

Save the returned `trade_reference` (e.g. `KS-abc123...`).

## 3. Submit the buyer instruction

The buyer's platform submits the matching instruction:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.keystoneos.xyz/v1/instructions \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "idempotency_key": "my-first-dvp-buyer",
      "trade_reference": "KS-abc123...",
      "template_slug": "dvp-standard",
      "role": "buyer",
      "party": {
        "external_reference": "buyer-001",
        "name": "Beta Capital",
        "wallet_address": "0xBuyerWallet..."
      },
      "legs": [
        {
          "leg_type": "asset_delivery",
          "instrument_id": "0xTokenAddress",
          "quantity": "100",
          "direction": "receive",
          "chain_id": 11155111
        },
        {
          "leg_type": "payment",
          "instrument_id": "0xUSDCAddress",
          "quantity": "50000",
          "direction": "deliver",
          "chain_id": 11155111
        }
      ],
      "timeout_at": "2026-03-17T00:00:00Z"
    }'
  ```

  ```typescript TypeScript SDK theme={null}
  const buyerInstruction = await client.instructions.submit({
    idempotencyKey: client.generateIdempotencyKey(),
    tradeReference: "KS-abc123...",
    templateSlug: "dvp-standard",
    role: "buyer",
    party: {
      externalReference: "buyer-001",
      name: "Beta Capital",
      walletAddress: "0xBuyerWallet...",
    },
    legs: [
      { legType: "asset_delivery", instrumentId: "0xTokenAddress", quantity: "100", direction: "receive", chainId: 11155111 },
      { legType: "payment", instrumentId: "0xUSDCAddress", quantity: "50000", direction: "deliver", chainId: 11155111 },
    ],
    timeoutAt: "2026-03-17T00:00:00Z",
  });

  console.log(buyerInstruction.status);       // "matched"
  console.log(buyerInstruction.settlementId); // "550e8400-..."
  ```

  ```python Python SDK theme={null}
  buyer_instruction = await client.instructions.submit({
      "idempotency_key": "my-first-dvp-buyer",
      "trade_reference": "KS-abc123...",
      "template_slug": "dvp-standard",
      "role": "buyer",
      "party": {
          "external_reference": "buyer-001",
          "name": "Beta Capital",
          "wallet_address": "0xBuyerWallet...",
      },
      "legs": [
          {"leg_type": "asset_delivery", "instrument_id": "0xTokenAddress", "quantity": "100", "direction": "receive", "chain_id": 11155111},
          {"leg_type": "payment", "instrument_id": "0xUSDCAddress", "quantity": "50000", "direction": "deliver", "chain_id": 11155111},
      ],
      "timeout_at": "2026-03-17T00:00:00Z",
  })

  print(buyer_instruction.status)         # "matched"
  print(buyer_instruction.settlement_id)  # "550e8400-..."
  ```
</CodeGroup>

<Note>
  The `idempotency_key` ensures safe retries. If you send the same key twice, the API returns the existing instruction instead of creating a duplicate.
</Note>

The response includes `status: "matched"` and a `settlement_id`. The settlement is created automatically on-chain.

## 4. Watch compliance run

After matching, the settlement engine screens all parties through LSEG World-Check (entity) and CipherOwl (wallet). Results are attested to the ComplianceRegistry on-chain, and the contract enforces that compliance must pass before the settlement can advance.

If a party is flagged, the settlement pauses at `COMPLIANCE_CHECKING`. A compliance officer reviews and submits a decision:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.keystoneos.xyz/v1/settlements/$SETTLEMENT_ID/compliance-decision \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"decision": "approve"}'
  ```

  ```typescript TypeScript SDK theme={null}
  const settlement = await client.compliance.approve("550e8400-...");
  ```

  ```python Python SDK theme={null}
  settlement = await client.compliance.approve("550e8400-...")
  ```
</CodeGroup>

If rejected, the settlement transitions to `ROLLED_BACK`.

## 5. Deposit to escrow

When the settlement reaches `AWAITING_DEPOSITS`, both parties deposit their assets directly to the escrow smart contract on-chain. Each leg in the settlement response includes a `deposit_secret` and `deposit_key`. Your platform calls `depositLeg(settlementId, legIndex, depositSecret)` on the escrow contract using its custody provider (such as MPC wallets or any signing infrastructure) to sign the transaction.

KeyStone is not involved in the deposit step. The escrow contract verifies `keccak256(depositSecret) == depositKey` to authorize the deposit - no address-based validation.

## 6. Contracts handle the rest

Once all deposits are confirmed, the contracts take over autonomously:

1. The last deposit triggers execution inline once the compliance gate passes
2. The coordinator verifies the atomicity gate (all legs deposited on all chains)
3. The contract pays every leg to its recipient bound at registration - one atomic transaction, all-or-nothing
4. Tokens go to the buyer's wallet, USDC goes to the seller's wallet
5. Settlement transitions to `FINALIZED`

## 7. Check the result

Track progress in the [KeyStone Dashboard](https://app.keystoneos.xyz) under **Settlements**, or via the API:

<CodeGroup>
  ```bash cURL theme={null}
  # Poll settlement status
  curl https://api.keystoneos.xyz/v1/settlements/$SETTLEMENT_ID \
    -H "Authorization: Bearer $TOKEN"

  # View event history
  curl https://api.keystoneos.xyz/v1/settlements/$SETTLEMENT_ID/events \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```typescript TypeScript SDK theme={null}
  // Get settlement status
  const settlement = await client.settlements.get("550e8400-...");
  console.log(settlement.state);

  // View event history
  const events = await client.settlements.events("550e8400-...");
  for (const event of events.items) {
    console.log(`${event.fromState} -> ${event.toState}`);
  }
  ```

  ```python Python SDK theme={null}
  # Get settlement status
  settlement = await client.settlements.get("550e8400-...")
  print(settlement.state)

  # View event history
  events = await client.settlements.events("550e8400-...")
  for event in events.items:
      print(f"{event.from_state} -> {event.to_state}")
  ```
</CodeGroup>

## What if something goes wrong?

* **Compliance rejection** - Settlement ends in `REJECTED`. No deposits were made at that point.
* **Deposit timeout** - If deposits are not received by `timeout_at`, the settlement transitions to `TIMED_OUT` and partial deposits become reclaimable. The operator or any depositor can trigger the timeout on-chain; it cannot be paused.
* **Execution failure** - The escrow contract rolls back, returning all deposits to their original owners.

Every failure path is deterministic and recorded in the event history. No funds are ever locked indefinitely.

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="book" href="/concepts/overview">
    Deep dive into settlements, templates, and the state machine.
  </Card>

  <Card title="Bilateral Instructions" icon="arrows-left-right" href="/guides/bilateral-instructions">
    Full guide to instruction submission, matching, and cancellation.
  </Card>
</CardGroup>
