This guide walks through a cross-platform DvP where Platform A’s seller delivers tokens to Platform B’s buyer.
Flow overview
Platform A creates the settlement with their own seller’s details inline, and specifies Platform B as the counterparty:
curl -X POST https://api.keystoneos.xyz/v1/settlements \
-H "Authorization: Bearer $PLATFORM_A_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "cross-dvp-001",
"template_id": "CROSS_PLATFORM_DvP_TEMPLATE",
"timeout_at": "2026-03-17T12:00:00Z",
"parties": [
{
"role": "seller",
"external_reference": "seller-001",
"name": "Acme Securities",
"wallet_address": "0xSellerWallet...",
"chain_id": 11155111
}
],
"counterparty_parties": [
{
"platform_slug": "platform-b",
"role": "buyer",
"wallet_address_hint": "0xBuyerHint...",
"counterparty_reference": "Acme Fund LLC"
}
],
"legs": [
{
"leg_type": "asset",
"instrument_id": "0xTokenAddress",
"quantity": "500",
"direction": "deliver",
"party_role": "seller"
},
{
"leg_type": "payment",
"instrument_id": "USDC",
"quantity": "125000",
"direction": "deliver",
"party_role": "buyer"
}
]
}'
The settlement is created with settlement_type: "cross_platform" and the engine pauses at AWAITING_CONFIRMATION.
Platform B’s webhook endpoint receives:
{
"event": "settlement.confirmation_required",
"data": {
"settlement_id": "stl-...",
"role": "buyer",
"wallet_address_hint": "0xBuyerHint...",
"counterparty_reference": "Acme Fund LLC",
"legs": [...]
}
}
Platform B uses the hints to identify which entity should be assigned to this settlement.
Platform B provides the actual party details for their side of the settlement:
curl -X POST https://api.keystoneos.xyz/v1/settlements/$SETTLEMENT_ID/confirm \
-H "Authorization: Bearer $PLATFORM_B_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"external_reference": "buyer-acct-042",
"name": "Beta Capital",
"wallet_address": "0xBuyerWallet...",
"chain_id": 11155111
}'
Platform B authenticates with its own M2M token. KeyStone verifies that Platform B has a pending party in this settlement.
Step 4: Settlement proceeds
Once all parties are confirmed, the engine resumes and processes the settlement through the normal flow: compliance, escrow registration, deposit monitoring, execution, and finalization.
Both platforms receive webhooks at every state transition.
Rejecting a settlement
If Platform B doesn’t want to participate:
curl -X POST https://api.keystoneos.xyz/v1/settlements/$SETTLEMENT_ID/reject \
-H "Authorization: Bearer $PLATFORM_B_TOKEN" \
-d '{"reason": "Entity not eligible"}'
The settlement transitions to a failure state. Platform A is notified via webhook.
Hints are optional
The wallet_address_hint and counterparty_reference fields in counterparty_parties are optional. They’re useful when:
- Same user across platforms - provide the wallet address hint
- Pre-agreed OTC trade - provide the entity name or LEI
- Unknown counterparty - omit both, Platform B assigns whoever they want
Platform B always has final say via the confirmation call.
Template differences
Cross-platform templates include an await_confirmation action that single-platform templates skip:
{
"INSTRUCTED": {
"type": "await_confirmation",
"provider": "internal",
"resolution": "manual"
}
}
This causes the engine to pause until all counterparties confirm (or one rejects).