Data Model: Remittances
Status: Draft | Owner: Platform Team | Last Updated: 2026-04-03
Overview
Remittance domain model for Simpaisa's cross-border payment corridors. Handles FX quoting, AML/KYC compliance, and multi-provider corridor routing across PK, BD, NP, and IQ. Extends the canonical Payment entity with corridor-specific fields for regulatory compliance and foreign exchange.
Entity: Remittance
Extends Payment from the canonical model.
| Field |
Type |
Description |
id |
string |
ULID (inherited) |
paymentId |
string |
FK → Payment (canonical) |
corridor |
string |
Source→Target code (e.g. "AE→PK") |
corridorConfigId |
string |
FK → CorridorConfig |
fxQuoteId |
string |
FK → FXQuote |
sourceAmount |
decimal |
Amount in source currency |
sourceCurrency |
Currency |
Sender's currency |
targetAmount |
decimal |
Amount in target currency |
targetCurrency |
Currency |
Receiver's currency |
amlStatus |
AMLStatus |
AML screening result |
amlCheckId |
string |
FK → AMLCheck |
senderKYC |
string |
FK → BeneficiaryKYC (sender) |
receiverKYC |
string |
FK → BeneficiaryKYC (receiver) |
senderId |
string |
Sender identity reference |
receiverId |
string |
Receiver identity reference |
purpose |
RemittancePurpose |
Purpose code (family support, salary, etc.) |
status |
RemittanceStatus |
9-state lifecycle |
providerId |
string |
Downstream remittance partner |
providerRef |
string |
Partner's transaction reference |
complianceNotes |
string |
Regulatory notes (encrypted) |
createdAt |
datetime |
Inherited |
updatedAt |
datetime |
Inherited |
Entity: FXQuote
| Field |
Type |
Description |
id |
string |
ULID |
sourceCurrency |
string |
ISO 4217 |
targetCurrency |
string |
ISO 4217 |
sourceAmount |
decimal |
Quoted source amount |
targetAmount |
decimal |
Quoted target amount |
rate |
decimal |
Mid-market rate (precision 8) |
markup |
decimal |
Simpaisa margin (basis points) |
effectiveRate |
decimal |
Rate presented to customer |
provider |
string |
Rate source (e.g. Reuters, XE) |
lockedAt |
datetime |
Timestamp rate was locked |
expiresAt |
datetime |
Quote expiry (typically 30s–5min) |
status |
QuoteStatus |
QUOTED, LOCKED, EXECUTED, EXPIRED |
usedByRemittanceId |
string |
FK → Remittance (nullable until used) |
Entity: AMLCheck
| Field |
Type |
Description |
id |
string |
ULID |
remittanceId |
string |
FK → Remittance |
checkType |
AMLCheckType |
SANCTIONS, PEP, ADVERSE_MEDIA, VELOCITY |
provider |
string |
Screening provider (e.g. Refinitiv) |
senderScore |
int |
Risk score 0–100 |
receiverScore |
int |
Risk score 0–100 |
result |
AMLResult |
CLEAR, REVIEW, BLOCK |
matchDetails |
string |
Matched entity details (encrypted) |
checkedAt |
datetime |
Screening timestamp |
reviewedBy |
string |
Compliance officer (nullable) |
reviewedAt |
datetime |
Manual review timestamp (nullable) |
Entity: BeneficiaryKYC
| Field |
Type |
Description |
id |
string |
ULID |
fullName |
string |
Legal name as per ID |
dateOfBirth |
date |
DoB for sanctions screening |
nationality |
string |
ISO 3166-1 alpha-2 |
idType |
IDType |
PASSPORT, NATIONAL_ID, DRIVING_LICENCE |
idNumber |
string |
Document number (encrypted) |
idExpiry |
date |
Document expiry date |
country |
string |
Country of residence |
address |
string |
Residential address (encrypted) |
riskRating |
RiskRating |
LOW, MEDIUM, HIGH |
verifiedAt |
datetime |
KYC verification timestamp |
expiresAt |
datetime |
KYC validity end (annual refresh) |
status |
KYCStatus |
PENDING, VERIFIED, EXPIRED, REJECTED |
Entity: CorridorConfig
| Field |
Type |
Description |
id |
string |
ULID |
corridorCode |
string |
e.g. "AE→PK", "UK→BD" |
sourceCurrency |
string |
ISO 4217 |
targetCurrency |
string |
ISO 4217 |
providers |
[]string |
Ordered list of provider IDs (priority) |
minAmount |
decimal |
Minimum transaction amount (source) |
maxAmount |
decimal |
Maximum per-transaction (source) |
dailyLimit |
decimal |
Daily aggregate limit per sender |
monthlyLimit |
decimal |
Monthly aggregate limit per sender |
amlProvider |
string |
AML screening provider for this corridor |
requiredKYCLevel |
string |
KYC tier required (BASIC, ENHANCED) |
status |
CorridorStatus |
ACTIVE, SUSPENDED, CLOSED |
regulatoryNotes |
string |
Country-specific compliance notes |
Remittance 9-State Machine
┌──────────┐
│ CREATED │
└────┬─────┘
│ lock FX quote
▼
┌──────────┐
│FX_LOCKED │
└────┬─────┘
│ initiate AML
▼
┌────────────┐
│AML_PENDING │
└──┬──────┬──┘
│ │
clear block
│ │
│ ▼
│ ┌──────────┐
│ │AML_BLOCKED│──────────────┐
│ └──────────┘ │
▼ │
┌────────────┐ │
│ AUTHORISED │ │
└────┬───────┘ │
│ submit to provider │
▼ │
┌────────────┐ │
│ PROCESSING │ │
└──┬──────┬──┘ │
│ │ │
success failure │
│ │ │
▼ ▼ │
┌──────────┐ ┌────────┐ │
│COMPLETED │ │ FAILED │ │
└──────────┘ └────────┘ │
│ │
▼ ▼
┌──────────────────────┐
│ CANCELLED │
└──────────────────────┘
Key Transitions:
- CREATED → FX_LOCKED: FX quote accepted and locked
- FX_LOCKED → AML_PENDING: AML/sanctions screening initiated
- AML_PENDING → AUTHORISED: All checks clear
- AML_PENDING → AML_BLOCKED: Sanctions hit or high-risk alert
- AUTHORISED → PROCESSING: Submitted to corridor provider
- PROCESSING → COMPLETED: Provider confirms delivery
- PROCESSING → FAILED: Provider rejects or timeout
- FAILED → CANCELLED: Funds returned, FX quote released
- AML_BLOCKED → CANCELLED: Compliance review rejects
Entity Relationships (ERD)
┌──────────────┐1 N┌─────────────┐1 1┌──────────┐
│CorridorConfig│──────│ Remittance │──────│ FXQuote │
└──────────────┘ └──────┬──────┘ └──────────┘
│1 │1
│ │
1│ 1│
┌─────┴┐ ┌┴───────────┐
│AMLChk│ │BeneficiaryKYC│
└──────┘ └────────────┘
(sender + receiver)
Enumerations
| Enum |
Values |
RemittanceStatus |
CREATED, FX_LOCKED, AML_PENDING, AML_BLOCKED, AUTHORISED, PROCESSING, COMPLETED, FAILED, CANCELLED |
AMLStatus |
NOT_CHECKED, PENDING, CLEAR, REVIEW, BLOCKED |
AMLCheckType |
SANCTIONS, PEP, ADVERSE_MEDIA, VELOCITY |
AMLResult |
CLEAR, REVIEW, BLOCK |
QuoteStatus |
QUOTED, LOCKED, EXECUTED, EXPIRED |
KYCStatus |
PENDING, VERIFIED, EXPIRED, REJECTED |
RiskRating |
LOW, MEDIUM, HIGH |
RemittancePurpose |
FAMILY_SUPPORT, SALARY, EDUCATION, MEDICAL, TRADE, OTHER |
CorridorStatus |
ACTIVE, SUSPENDED, CLOSED |
SurrealDB Table Mapping
DEFINE TABLE remittance SCHEMAFULL;
DEFINE FIELD paymentId ON remittance TYPE record<payment>;
DEFINE FIELD corridor ON remittance TYPE string;
DEFINE FIELD corridorConfigId ON remittance TYPE record<corridor_config>;
DEFINE FIELD fxQuoteId ON remittance TYPE record<fx_quote>;
DEFINE FIELD sourceAmount ON remittance TYPE decimal;
DEFINE FIELD sourceCurrency ON remittance TYPE string;
DEFINE FIELD targetAmount ON remittance TYPE decimal;
DEFINE FIELD targetCurrency ON remittance TYPE string;
DEFINE FIELD amlStatus ON remittance TYPE string;
DEFINE FIELD amlCheckId ON remittance TYPE option<record<aml_check>>;
DEFINE FIELD senderKYC ON remittance TYPE record<beneficiary_kyc>;
DEFINE FIELD receiverKYC ON remittance TYPE record<beneficiary_kyc>;
DEFINE FIELD status ON remittance TYPE string
ASSERT $value IN ['CREATED','FX_LOCKED','AML_PENDING','AML_BLOCKED','AUTHORISED','PROCESSING','COMPLETED','FAILED','CANCELLED'];
DEFINE FIELD createdAt ON remittance TYPE datetime DEFAULT time::now();
DEFINE INDEX idx_remit_corridor ON remittance FIELDS corridor;
DEFINE INDEX idx_remit_status ON remittance FIELDS status;
DEFINE INDEX idx_remit_sender ON remittance FIELDS senderKYC;
DEFINE TABLE fx_quote SCHEMAFULL;
DEFINE FIELD sourceCurrency ON fx_quote TYPE string;
DEFINE FIELD targetCurrency ON fx_quote TYPE string;
DEFINE FIELD sourceAmount ON fx_quote TYPE decimal;
DEFINE FIELD targetAmount ON fx_quote TYPE decimal;
DEFINE FIELD rate ON fx_quote TYPE decimal;
DEFINE FIELD markup ON fx_quote TYPE decimal;
DEFINE FIELD effectiveRate ON fx_quote TYPE decimal;
DEFINE FIELD lockedAt ON fx_quote TYPE datetime;
DEFINE FIELD expiresAt ON fx_quote TYPE datetime;
DEFINE FIELD status ON fx_quote TYPE string;
DEFINE TABLE aml_check SCHEMAFULL;
DEFINE FIELD remittanceId ON aml_check TYPE record<remittance>;
DEFINE FIELD checkType ON aml_check TYPE string;
DEFINE FIELD provider ON aml_check TYPE string;
DEFINE FIELD senderScore ON aml_check TYPE int;
DEFINE FIELD receiverScore ON aml_check TYPE int;
DEFINE FIELD result ON aml_check TYPE string;
DEFINE FIELD checkedAt ON aml_check TYPE datetime;
DEFINE TABLE beneficiary_kyc SCHEMAFULL;
DEFINE FIELD fullName ON beneficiary_kyc TYPE string;
DEFINE FIELD dateOfBirth ON beneficiary_kyc TYPE datetime;
DEFINE FIELD nationality ON beneficiary_kyc TYPE string;
DEFINE FIELD idType ON beneficiary_kyc TYPE string;
DEFINE FIELD idNumber ON beneficiary_kyc TYPE string; -- encrypted at app layer
DEFINE FIELD riskRating ON beneficiary_kyc TYPE string;
DEFINE FIELD status ON beneficiary_kyc TYPE string;
DEFINE FIELD verifiedAt ON beneficiary_kyc TYPE option<datetime>;
DEFINE TABLE corridor_config SCHEMAFULL;
DEFINE FIELD corridorCode ON corridor_config TYPE string;
DEFINE FIELD sourceCurrency ON corridor_config TYPE string;
DEFINE FIELD targetCurrency ON corridor_config TYPE string;
DEFINE FIELD providers ON corridor_config TYPE array<string>;
DEFINE FIELD minAmount ON corridor_config TYPE decimal;
DEFINE FIELD maxAmount ON corridor_config TYPE decimal;
DEFINE FIELD dailyLimit ON corridor_config TYPE decimal;
DEFINE FIELD monthlyLimit ON corridor_config TYPE decimal;
DEFINE FIELD status ON corridor_config TYPE string;
DEFINE INDEX idx_corridor_code ON corridor_config FIELDS corridorCode UNIQUE;