1. BEC Settlement Policy
A settlement is considered BEC-resistant only when all six conditions are satisfied:
- Entity identity verified - VC reference + hash for both sender and receiver
- Authorized signer signs canonical payload - Ed25519 signature over deterministic JSON
- Beneficiary account ownership independently verified - Bank attestation or micro-deposit proof
- Receiver confirms settlement instructions - Required for medium/high risk tiers
- ATCE policy engine evaluates risk - Machine-readable decision with scored reasons
- Settlement receipt generated - Immutable evidence summary anchored to ledger
2. API Design Principles
- Deterministic canonical hashing - Sorted keys, UTF-8, SHA-256 or Keccak-256
- Idempotent request handling - Duplicate
idempotency_keyreturns existing result - Evidence-driven - Flexible JSON evidence ingestion (bank attestations, OOB confirmations, document hashes)
- Machine-readable policy decisions - Scored risk tiers with actionable reason codes
- Receipts suitable for ledger anchoring - Every receipt includes Merkle proof and state root
3. API Endpoints
Create Settlement Request
POST/v1/settlements
Sender-initiated settlement request. Requires Idempotency-Key header. The request must include sender/receiver identity blocks, beneficiary account with ownership proof, intent declaration, and at least one Ed25519 signature.
| Response | Description |
|---|---|
201 | Created - returns SettlementStatus |
400 | Bad Request - validation failure |
409 | Conflict - duplicate idempotency key |
Get Settlement Status
GET/v1/settlements/{request_id}
Returns current settlement status, latest policy decision, and receipt if settled.
Submit Receiver Acceptance
POST/v1/settlements/{request_id}/accept
Required for medium and high risk tiers (T2/T3). The receiver's authorized signer confirms beneficiary account details and signs the acceptance hash.
Submit Evidence Bundle
POST/v1/settlements/{request_id}/evidence
Attach evidence items to a settlement. Accepted types:
| Type | Description |
|---|---|
BANK_ATTESTATION | Bank-issued proof of account ownership |
VC_REFERENCE | Verifiable credential pointer |
OOB_CONFIRMATION | Out-of-band callback confirmation |
DOCUMENT_HASH | Invoice, contract, or supporting document hash |
QUORUM_APPROVAL | Multi-sig or quorum approval record |
CALLBACK_RECORD | Automated callback verification log |
Evaluate Policy (ATCE)
POST/v1/settlements/{request_id}/evaluate
Runs the ATCE (Automated Transaction Compliance Engine) evaluation. Returns a machine-readable policy decision with risk score, tier classification, reason codes, and required actions.
Commit Settlement
POST/v1/settlements/{request_id}/commit
Commits the settlement if policy decision is APPROVE and all required actions are satisfied. Returns the final settlement receipt with evidence summary, policy summary, and router signature. Supports dry_run: true for pre-commit validation.
4. Settlement Request Schema
Schema version: jil.bec.settlement_request.v1
4.1 Core Fields
| Field | Type | Required | Description |
|---|---|---|---|
request_id | string | Yes | Unique settlement identifier |
idempotency_key | string | Yes | Prevent duplicate processing |
created_at | ISO 8601 | Yes | Request timestamp |
expires_at | ISO 8601 | Yes | Request TTL |
4.2 Corridor
| Field | Type | Required | Description |
|---|---|---|---|
rail_type | enum | Yes | FIAT_FIAT, FIAT_CRYPTO, CRYPTO_CRYPTO |
currency | string | Yes | ISO currency or token symbol |
jurisdiction_sender | string | Yes | Sender jurisdiction (ISO 3166) |
jurisdiction_receiver | string | Yes | Receiver jurisdiction (ISO 3166) |
corridor_id | string | Yes | Corridor identifier (e.g. US-CH-USD-01) |
4.3 Sender Identity (with Authorized Signer)
| Field | Required | Description |
|---|---|---|
sender.entity_id | Yes | Unique entity identifier |
sender.legal_name | Yes | Registered legal name |
sender.registration.country | Yes | Registration country |
sender.registration.number | Yes | Registration number |
sender.vc_ref | Yes | Verifiable credential reference |
sender.vc_hash | Yes | Hash of referenced VC |
sender.authorized_signer.public_key | Yes | Ed25519 public key |
sender.authorized_signer.role | Yes | CFO, Treasurer, Controller, etc. |
4.4 Receiver Identity
| Field | Required | Description |
|---|---|---|
receiver.entity_id | Yes | Unique entity identifier |
receiver.legal_name | Yes | Registered legal name |
receiver.registration | Yes | Country + registration number |
receiver.vc_ref | Yes | Verifiable credential reference |
receiver.vc_hash | Yes | Hash of referenced VC |
4.5 Beneficiary Account (FIAT rails)
| Field | Required | Description |
|---|---|---|
account_type | Yes | BANK or WALLET |
account_holder_name | Yes | Name on account |
iban_or_account | Yes | IBAN, BBAN, or wallet address |
bic_swift | Yes | BIC/SWIFT code |
bank_name | Yes | Receiving bank name |
ownership_proof.method | Yes | BANK_ATTESTATION, MICRO_DEPOSIT, OTHER |
ownership_proof.hash | Yes | Hash of proof artifact |
ownership_proof.issuer | Yes | Issuer identifier (e.g. bank:examplebank) |
ownership_proof.issued_at | Yes | When proof was issued |
4.6 Intent + Signatures
| Field | Required | Description |
|---|---|---|
intent.intent_text | One of | Human-readable settlement intent |
intent.intent_hash | One of | Pre-hashed intent (if text omitted) |
signatures[].type | Yes | SENDER_INTENT_SIGNATURE |
signatures[].signature | Yes | Base64-encoded Ed25519 signature |
signatures[].signed_payload_hash | Yes | Hash of canonical payload that was signed |
5. Settlement Acceptance
Required for medium/high risk tiers. The receiver's authorized signer confirms the beneficiary account and settlement details.
Schema version: jil.bec.settlement_acceptance.v1
| Field | Required | Description |
|---|---|---|
acceptance_id | Yes | Unique acceptance identifier |
receiver.entity_id | Yes | Must match original receiver |
receiver.authorized_signer | Yes | Receiver's signing authority |
acceptance.accept_hash | Yes | Hash of acceptance content |
signatures[] | Yes | RECEIVER_ACCEPT_SIGNATURE |
6. ATCE Policy Decision
Schema version: jil.bec.policy_decision.v1
The ATCE engine evaluates each settlement and returns a structured decision:
| Field | Type | Description |
|---|---|---|
decision | enum | APPROVE HOLD_REVIEW REJECT |
risk_score | integer | 0-100 composite risk score |
tier | enum | T0 (low) through T3 (critical) |
reasons[] | array | Machine-readable reason codes |
required_actions[] | array | Actions needed before commit |
policy_hash | string | Hash of the policy ruleset used |
engine_version | string | ATCE engine version (e.g. atce-1.7.3) |
Risk Tiers
| Tier | Score Range | Behavior |
|---|---|---|
| T0 | 0-10 | Auto-approve, no acceptance required |
| T1 | 11-30 | Auto-approve, acceptance optional |
| T2 | 31-60 | Acceptance required, may require OOB |
| T3 | 61-100 | Manual review, dual approval, cooling-off |
Required Actions
| Action | Description |
|---|---|
OOB_REQUIRED | Out-of-band confirmation via registered callback |
COOLING_OFF | Mandatory delay before commit |
DUAL_APPROVAL | Two authorized signers required |
NAME_MATCH_STRICT | Beneficiary name must exactly match registration |
BANK_ATTESTATION_REQUIRED | Fresh bank attestation needed |
7. Settlement Receipt
Schema version: jil.bec.settlement_receipt.v1
The final settlement artifact - immutable, auditable, and suitable for ledger anchoring.
| Field | Description |
|---|---|
status | SETTLED or FAILED |
final_settlement.rail_type | Settlement rail used |
final_settlement.amount | Final settled amount |
final_settlement.beneficiary_account_fingerprint | SHA-256 fingerprint of beneficiary account |
final_settlement.settlement_tx_id | Ledger transaction ID |
final_settlement.ledger_receipt_root | Merkle receipt root |
evidence_summary | Hashes of all evidence: sender VC, receiver VC, bank attestation, intent, acceptance |
policy_summary | Decision, tier, risk score, policy hash |
signatures[] | ROUTER_RECEIPT_SIGNATURE - Ed25519 signature from the settlement router |
8. Canonical Hashing Rules
All signatures must be generated over deterministic canonical payloads. This prevents payload mutation attacks.
- Canonical JSON - Sorted keys, UTF-8 encoding, no trailing whitespace
- Hash - SHA-256 or Keccak-256 of the canonical JSON bytes
- Sign - Ed25519 signature over the hash
- Include -
signed_payload_hashmust be included in every signature object
signed_payload_hash. If they differ, the request is rejected with PAYLOAD_HASH_MISMATCH.
9. Status Lifecycle
Settlements traverse the following state machine. Each transition is deterministic and produces an auditable event.
Terminal states:
10. Request/Response Examples
10.1 Settlement Request (FIAT_FIAT, $5M)
{
"schema_version": "jil.bec.settlement_request.v1",
"request_id": "srq_01JXYZ123456",
"idempotency_key": "4d1b5c66-9b9a-4f7f-b4f1-43a1b0a7f7b9",
"created_at": "2026-02-26T14:05:22Z",
"expires_at": "2026-02-27T14:05:22Z",
"corridor": {
"rail_type": "FIAT_FIAT",
"currency": "USD",
"jurisdiction_sender": "US",
"jurisdiction_receiver": "CH",
"corridor_id": "US-CH-USD-01"
},
"amount": { "value": "5000000.00", "currency": "USD" },
"sender": {
"entity_id": "ent_sender_123",
"legal_name": "ABC Capital Partners LLC",
"registration": { "country": "US", "state": "DE", "number": "1234567" },
"vc_ref": "vc:kyb:partnerX:abcdef",
"vc_hash": "0xaaa111",
"authorized_signer": {
"signer_id": "sig_abc_cfo",
"public_key": "ed25519:senderpubkey",
"role": "CFO",
"auth_method": ["PASSKEY", "MPC_QUORUM"]
}
},
"receiver": {
"entity_id": "ent_receiver_456",
"legal_name": "XYZ Trading AG",
"registration": { "country": "CH", "number": "CHE-123.456.789" },
"vc_ref": "vc:kyb:partnerY:12345",
"vc_hash": "0xbbb222"
},
"beneficiary_account": {
"account_type": "BANK",
"account_holder_name": "XYZ Trading AG",
"iban_or_account": "CH93-0000-0000-0000-0000-0",
"bic_swift": "XYZBCHZZ",
"bank_name": "Example Bank",
"ownership_proof": {
"method": "BANK_ATTESTATION",
"hash": "0xccc333",
"issued_at": "2026-02-25T10:00:00Z",
"issuer": "bank:examplebank"
}
},
"intent": {
"intent_text": "ABC Capital Partners LLC authorizes settlement of 5,000,000.00 USD to XYZ Trading AG per INV-99321."
},
"signatures": [{
"type": "SENDER_INTENT_SIGNATURE",
"signer_public_key": "ed25519:senderpubkey",
"signature": "base64:AAABBBCCC",
"signed_payload_hash": "0xpayloadhash1"
}]
}
10.2 Receiver Acceptance
{
"schema_version": "jil.bec.settlement_acceptance.v1",
"request_id": "srq_01JXYZ123456",
"acceptance_id": "sac_01JABC987654",
"accepted_at": "2026-02-26T15:02:00Z",
"receiver": {
"entity_id": "ent_receiver_456",
"authorized_signer": {
"signer_id": "sig_xyz_treasury",
"public_key": "ed25519:receiverpubkey",
"role": "Treasury"
}
},
"acceptance": {
"accept_text": "XYZ Trading AG confirms beneficiary account CH93... for settlement INV-99321.",
"accept_hash": "sha256:acceptancehash"
},
"signatures": [{
"type": "RECEIVER_ACCEPT_SIGNATURE",
"signer_public_key": "ed25519:receiverpubkey",
"signature": "base64:DDD111EEE",
"signed_payload_hash": "0xpayloadhash_accept"
}]
}
10.3 Evidence Bundle
{
"schema_version": "jil.bec.evidence_bundle.v1",
"request_id": "srq_01JXYZ123456",
"items": [
{
"type": "BANK_ATTESTATION",
"hash": "0xccc333",
"issuer": "bank:examplebank",
"issued_at": "2026-02-25T10:00:00Z",
"ref": "bat_01JATTEST"
},
{
"type": "OOB_CONFIRMATION",
"hash": "0xoob444",
"issuer": "oob:registered_callback",
"issued_at": "2026-02-26T14:55:00Z",
"metadata": { "method": "REGISTERED_CALLBACK", "result": "CONFIRMED" }
},
{
"type": "DOCUMENT_HASH",
"hash": "sha256:8f14e45fceea167a5a36dedd4bea2543",
"issuer": "doc:sender",
"issued_at": "2026-02-26T14:05:22Z"
}
]
}
10.4 Policy Decision (APPROVE)
{
"schema_version": "jil.bec.policy_decision.v1",
"request_id": "srq_01JXYZ123456",
"evaluated_at": "2026-02-26T15:05:12Z",
"decision": "APPROVE",
"risk_score": 21,
"tier": "T3",
"reasons": [],
"required_actions": [],
"policy_hash": "0xpol123",
"engine_version": "atce-1.7.3",
"policy_receipt_signature": "base64:ATCE_SIG"
}
10.5 Settlement Receipt (SETTLED)
{
"schema_version": "jil.bec.settlement_receipt.v1",
"request_id": "srq_01JXYZ123456",
"status": "SETTLED",
"settled_at": "2026-02-26T15:10:02Z",
"final_settlement": {
"rail_type": "FIAT_FIAT",
"amount": { "value": "5000000.00", "currency": "USD" },
"beneficiary_account_fingerprint": "fp:sha256:beneficiaryfp",
"settlement_tx_id": "jiltx_0xabc123",
"ledger_receipt_root": "0xreceiptroot",
"proofs": {
"receipt_merkle_proof": "base64:PROOF",
"state_root": "0xstateroot"
}
},
"evidence_summary": {
"sender_vc_hash": "0xaaa111",
"receiver_vc_hash": "0xbbb222",
"bank_attestation_hash": "0xccc333",
"intent_hash": "sha256:intenthash",
"acceptance_hash": "sha256:acceptancehash"
},
"policy_summary": {
"decision": "APPROVE",
"tier": "T3",
"risk_score": 21,
"policy_hash": "0xpol123"
},
"signatures": [{
"type": "ROUTER_RECEIPT_SIGNATURE",
"signer_public_key": "ed25519:routerpubkey",
"signature": "base64:ROUTER_SIG",
"signed_payload_hash": "0xreceiptpayloadhash"
}]
}
11. Service Method Signatures
Language-agnostic method signatures that map directly to the REST endpoints:
SettlementService
CreateSettlementRequest(request, idempotencyKey) -> SettlementStatus
GetSettlement(requestId) -> SettlementStatus
SubmitAcceptance(requestId, acceptance) -> SettlementStatus
SubmitEvidence(requestId, evidence) -> SettlementStatus
EvaluatePolicy(requestId) -> PolicyDecision
CommitSettlement(requestId, options?) -> SettlementReceipt
Validation Rules
- Verify canonical payload hash matches
signed_payload_hashfor each signature - Verify signer authorization (role + key mapping) before accepting signatures
- Enforce state machine transitions - no backward moves, no skipping states
12. Go-Live Runbook
Pre-Go-Live Checklist
- Confirm canonical JSON rules are identical across SDKs
- Confirm Ed25519 signature verification passes known test vectors
- Confirm idempotency storage is durable and low latency
- Confirm ATCE engine version and policy hash are pinned for release
- Confirm bank attestation issuer allowlist is configured per corridor
- Confirm logging includes
request_id,payload_hash, and decision codes
Operational Monitoring
| Metric | Alert Threshold |
|---|---|
createSettlementRequest rate | Sudden drop or spike |
evaluatePolicy latency | > 2s p99 |
| HOLD_REVIEW percentage by corridor | > 15% of requests |
| REJECT reasons distribution | New reason codes appearing |
| NEW_BENEFICIARY spikes | > 3x baseline |
| NAME_MISMATCH increases | > 2x baseline |
| OOB_REQUIRED failures | Any sustained failures |
commitSettlement conflict rate | > 1% |
Incident Playbook
- Bank attestation issuer outage: Move corridor to HOLD_REVIEW with OOB_REQUIRED
- Signature verification errors spike: Freeze commits and verify canonicalization mismatch