The settlement engine supports three distinct lanes, each with different compliance paths and attestation requirements.
Fiat-to-Fiat (FI-to-FI)
Traditional cross-border bank settlement - complements existing SWIFT/DTCC rails with atomic finality.
Type:SIMPLE Compliance: Single check (KYC/AML/sanctions) Attestation: Auto-transition from accepted to ready Travel Rule: FATF Wire Transfer Rule evaluation required Party Data: Legal name, account ID, country, address Example: Bank A (USD) → Bank B (EUR) Fees: 35-90 bps per event, $1 floor (vs 50-100 bps SWIFT)
Fiat-to-Crypto (FI-to-Crypto)
On-ramp settlement for institutional crypto acquisition.
Type:SIMPLE or DVP Compliance: Per-leg for DVP, single for SIMPLE Attestation: DVP requires leg attestation per counterparty Travel Rule: Applies to fiat leg DVP Example: Fiat delivery (leg 1) vs crypto delivery (leg 2) Example: Fund deposits USD → receives JIL/BTC/ETH
Crypto-to-Crypto
Cross-chain or same-chain token swaps with atomic execution.
Type:DVP or PVP Compliance: Per-leg compliance, per-leg attestation Attestation: Both legs must attest ready via POST /:id/attest-ready PVP: Concurrent asset exchange (both legs atomic) Example: Swap wBTC-JIL → wETH-JIL atomically Finality: Both legs marked "settled" at FINAL
Settlement Type Rules
SIMPLE settlements have a single compliance check and auto-transition from ACCEPTED to READY with no manual attestation.
DVP (Delivery vs Payment) has two legs - each leg is independently compliance-checked, and each counterparty must attest their leg as ready.
PVP (Payment vs Payment) is a concurrent asset exchange - both legs must be attested before either can proceed to L1 submission.
Atomic failure: if one leg of a DVP/PVP settlement is denied by compliance, the entire settlement is rejected.
02Settlement State Machine - Happy Path
The 8-step happy path from client submission through finality. Each state transition is driven by the settlement engine's poll loop running at ENGINE_POLL_INTERVAL_MS (default 2000ms).
1
RECEIVED - Client Submits Settlement Intent
Client submits a settlement request via POST /v1/settlements.
The engine creates a settlement record with a UUID and assigns a UETR (Unique End-to-End Transaction Reference).
An expiry timer is set (default 60 minutes via SETTLEMENT_EXPIRY_MINUTES).
Travel rule evaluation runs immediately - if the settlement involves fiat legs, FATF Wire Transfer Rule
checks are applied to validate party data (legal name, account identifier, country, address).
If travel rule fails → REJECTED.
If passes → VALIDATED.
Client SDKsettlement-api :8050
travel rule passed
2
VALIDATED - Schema Verified, Compliance Initiated
Schema validation complete and travel rule passed. The settlement engine now initiates compliance checks.
For SIMPLE settlements, a single compliance check covers the entire settlement
(KYC, AML, sanctions screening). For DVP / PVP
settlements, each leg triggers an independent compliance check. The compliance request is dispatched to
compliance-api :8100 with zone-specific screening parameters.
settlement-api :8050compliance-api :8100
compliance request dispatched
3
COMPLIANCE_CHECK - ZK Compliance Proofs Generated
The compliance API generates zero-knowledge compliance proofs for each required check.
KYC verification, AML screening, and sanctions list evaluation run per compliance zone.
A compliance receipt hash is computed and stored for auditability.
For DVP/PVP: each leg is independently evaluated. Compliance is atomic - if any leg
is denied, the entire settlement is rejected (one leg fails = whole settlement fails).
If any leg denied → REJECTED.
If all pass (decision = "allow") → ACCEPTED.
Compliance checks have passed. What happens next depends on the settlement type:
SIMPLE: Auto-transition to READY immediately. No manual attestation needed - the engine
moves the settlement forward on the next poll tick.
DVP/PVP: The settlement enters a waiting state. Each counterparty must confirm
their leg via POST /v1/settlements/:id/attest-ready. The engine holds
at ACCEPTED until all legs are attested. Once every leg has been attested → READY.
settlement-api :8050settlement-consumer :8051
all legs attested (or auto for SIMPLE)
5
READY - All Preconditions Met, Submitting to L1
All preconditions are satisfied. The settlement engine submits the transaction to JIL L1 via the
ledger-router :8000. An L1 tx_id is assigned
upon successful submission.
For DVP/PVP settlements, the primary leg is used for L1 submission. The ledger-router coordinates
multi-leg atomic execution on the L1 engine.
If L1 submission fails → FAILED.
If succeeds → SUBMITTED.
ledger-router :8000ledger-service :8001
tx_id assigned, included in mempool
6
SUBMITTED - Transaction Included in Block
The transaction has been included in a JIL L1 block. The engine records the block height
(block_height) and block hash (block_hash).
A confirmation counter begins tracking subsequent blocks.
A submission timeout is enforced - if the transaction is not confirmed within the timeout window,
the settlement transitions to FAILED.
If timeout → FAILED.
If block inclusion confirmed → CONFIRMED.
jil5600-core (Rust L1)settlement-consumer :8051
block confirmed, tracking confirmations
7
CONFIRMED - Accumulating Confirmations
The block containing this settlement has been included in the chain. Confirmations accumulate
with each new block produced after the settlement's block. The finality threshold is
FINALITY_CONFIRMATIONS=6 (default).
The engine re-checks the confirmation count on each poll tick (ENGINE_POLL_INTERVAL_MS).
Once the threshold is met → FINAL.
finality-proversettlement-consumer :8051
6 confirmations reached
8
FINAL - Settlement Complete
Finality threshold met. The settlement engine performs the following final operations:
1. Fee calculated at finality (SETTLEMENT_FEE_BPS=35, i.e. 35-90 bps per event, $1 floor). 2. Settlement receipt assembled with all proofs and metadata. 3. Finality proof stored in the proof store. 4. For DVP/PVP: all legs marked as "settled". 5. Webhook dispatched to the client's registered callback URL. 6. Kafka event published: SETTLEMENT_FINAL. 7. Batch settlement counts updated.
For multi-leg settlements (DVP and PVP), the engine holds at the ACCEPTED state until all counterparties have
confirmed their legs. This section details the attestation branching.
DVP/PVP Attestation Rules
Each leg has its own compliance check result, stored independently.
Counterparties attest their leg via POST /v1/settlements/:id/attest-ready with their leg identifier.
The engine tracks attestation status per leg. A settlement only moves to READY when all legs are attested.
Attestation is idempotent - re-attesting an already-attested leg has no effect.
If the settlement expires before all legs are attested, it transitions to EXPIRED.
PVP settlements require concurrent execution - both legs are submitted atomically to L1.
A
ACCEPTED - DVP/PVP Waiting for Attestations
Settlement is compliance-approved. The engine creates attestation slots for each leg.
Counterparty A has confirmed their leg. The engine updates the attestation record.
Settlement remains at ACCEPTED because not all legs are attested yet.
POST /v1/settlements/{id}/attest-ready
{ "leg_id":"leg_1", "party_id":"counterparty_a" }
settlement-api :8050
counterparty_b calls attest-ready
C
All Legs Attested - Transition to READY
Both counterparties have attested their legs. On the next engine poll tick, the settlement
transitions from ACCEPTED to READY and proceeds to L1 submission.
For PVP: both legs are bundled into a single atomic L1 transaction.
For DVP: the primary leg is submitted first, with the secondary leg following once the primary is confirmed.
settlement-api :8050ledger-router :8000
04Terminal Failure States
Settlements can exit the happy path and reach a terminal failure state at several points in the lifecycle.
×
REJECTED - Travel Rule or Compliance Failure
The settlement has been permanently rejected due to a compliance failure. This is a terminal state - no recovery is possible.
Causes:
• Travel rule evaluation failed (missing or invalid party data)
• KYC check failed (unverified counterparty)
• AML screening flagged (suspicious activity pattern)
• Sanctions list match (OFAC, EU, UN)
• Any single leg denied in a DVP/PVP settlement (atomic rejection)
Can occur from: RECEIVED, VALIDATED, COMPLIANCE_CHECK
compliance-api :8100settlement-api :8050
terminal - no recovery
×
FAILED - L1 Submission or Confirmation Failure
The settlement failed during the execution phase. This is a terminal state.
Causes:
• L1 transaction submission rejected by ledger-router (insufficient balance, invalid tx)
• L1 submission timeout (transaction not included in a block within the window)
• Block confirmation timeout (transaction included but chain stalled)
• L1 engine internal error (jil5600-core error)
Can occur from: READY, SUBMITTED
ledger-router :8000jil5600-core
terminal - no recovery
×
CANCELLED - Client-Initiated Cancellation
The client has explicitly cancelled the settlement via POST /v1/settlements/:id/cancel.
Cancellation is only permitted while the settlement is in a pre-execution state.
The settlement has exceeded its expiry deadline (default: SETTLEMENT_EXPIRY_MINUTES=60).
The engine checks expiry on each poll tick and automatically transitions stale settlements to EXPIRED.
Common causes:
• DVP/PVP settlement where one counterparty never attested their leg
• Compliance check took too long (external provider timeout)
• Client submitted but never completed follow-up actions
Can occur from: RECEIVED, VALIDATED, COMPLIANCE_CHECK, ACCEPTED
settlement-consumer :8051
05API Endpoints
Method
Endpoint
Purpose
Notes
POST
/v1/settlements
Create a new settlement
Returns settlement UUID and UETR. Body includes type (SIMPLE/DVP/PVP), parties, amount, asset, legs.
POST
/v1/settlements/batch
Batch create settlements
1-100 SIMPLE settlements per batch. Returns array of UUIDs. DVP/PVP not supported in batch.
POST
/v1/settlements/:id/cancel
Cancel a settlement
Only valid in states: received, validated, accepted, ready. Returns 409 if already submitted.
POST
/v1/settlements/:id/attest-ready
DVP/PVP leg attestation
Counterparty confirms their leg is ready. Body: { leg_id, party_id }. Idempotent.
GET
/v1/settlements/:id
Get settlement status
Returns full settlement record including current state, legs, compliance receipt, timestamps.
GET
/v1/settlements/:id/proof
Get finality proof
Only available when state = FINAL. Returns ZK compliance proof + L1 finality proof.
GET
/v1/settlements/:id/receipt
Get settlement receipt
Only available when state = FINAL. Returns full receipt with fee, block height, finality data.
Example: Create a SIMPLE Settlement
POST /v1/settlements
{ "type":"SIMPLE", "asset":"USD", "amount":"1000000.00", "sender": { "legal_name":"Acme Bank NA", "account_id":"acct_sender_001", "country":"US", "address":"123 Wall St, New York, NY 10005"
}, "receiver": { "legal_name":"Deutsche Finanz AG", "account_id":"acct_receiver_002", "country":"DE", "address":"Taunusanlage 12, 60325 Frankfurt"
}, "callback_url":"https://api.acmebank.com/webhooks/settlement"
}