Skip to main content
The data model was designed to ensure transactional integrity, audit traceability, and flexibility to support the different transfer flows. Entities are stored in PostgreSQL.

Main entities


Transfer

The Transfer entity is the central record for any type of transfer (TED OUT, TED IN, P2P). It stores sender and recipient details, amounts, and the current transaction state. Main fields:
FieldTypeDescription
transferIdUUID (PK)Unique transfer identifier
organizationIdUUID (FK)Multi-tenant isolation
ledgerIdUUIDFrom CRM (Midaz multi-tenant)
senderAccountIdUUIDSender’s Midaz account
recipientAccountIdUUID (nullable)Only for P2P
recipientDetailsJSONBISPB, branch, account, holder
amountDecimalAmount without fee
feeAmountDecimalFee charged
totalAmountDecimalamount + fee (calculated)
typeEnumTED_OUT, TED_IN, P2P
statusEnumCurrent transfer state
confirmationNumberStringHuman-readable number, unique per organization
controlNumberStringJD SPB NumCtrlIF
midazTransactionIdUUIDMidaz transaction reference

State machines

CREATED → PENDING → PROCESSING → COMPLETED
                               → REJECTED (4xx from JD)
                               → FAILED (5xx/timeout)
        → CANCELLED (user cancels before processing)

PaymentInitiation

Used in the TED OUT two-step flow, stores the transfer details so the client can review fees before confirming. An initiation expires in 24 hours if not processed. Main fields:
FieldTypeDescription
initiationIdUUID (PK)Unique identifier
organizationIdUUID (FK)Multi-tenant isolation
senderAccountIdUUIDSender account
recipientDetailsJSONBRecipient data
amountDecimalTransfer amount
feeAmountDecimalCalculated by plugin-fees
totalAmountDecimalamount + fee
statusEnumPENDING_CONFIRMATION, PROCESSED, EXPIRED
transferIdUUID (FK)Populated when PROCESSED
expiresAtTimestamp24h from creation
Lifecycle:
Created → User reviews fee → ProcessTransfer → PROCESSED
                                             → EXPIRED (after 24h)

TransferStatusHistory

Immutable audit log that records each state transition of the Transfer entity. Essential for traceability and compliance with BACEN’s 5-year data retention requirement. Main fields:
FieldTypeDescription
historyIdUUID (PK)Unique identifier
transferIdUUID (FK)Reference to Transfer
oldStatusEnum (nullable)Previous state
newStatusEnumNew state
reasonString (nullable)Reason (for error cases)
changedAtTimestampDate/time of change
changedByEnumsystem, user, admin
Retention: 5 years per BACEN regulatory requirement (Resolution 4.753/2019).

JDIncomingMessage

Persists raw messages received from the JD Consultores system before any processing. Ensures no incoming transfer (TED IN) is lost in case of failure, implementing at-least-once delivery guarantee. Deduplication is handled via the unique sequenceNumber constraint. Main fields:
FieldTypeDescription
organizationIdUUID (FK)Multi-tenant isolation
sequenceNumberString (unique)JD NumCabSeq (used for deduplication)
controlNumberString (nullable)NumCtrlIF
messageCodeEnumSTR0008R2, STR0010R2
returnTypeEnumP=Processed, E=Error, R=Receipt, C=Cancelled
rawXmlTextComplete JD message (audit)
processedBooleanfalse initially
transferIdUUID (FK)Populated after processing
Critical guarantee: The message is persisted BEFORE processing, ensuring no transfer is lost in case of failure. Duplicate messages are handled via the unique sequenceNumber constraint.

OrganizationConfig

Stores each client’s (tenant) specific configurations, such as JD credentials (encrypted), webhook URL, and fee settings. Main fields:
FieldTypeDescription
organizationIdUUID (PK)Same as JWT tenantId
jdCredentialsJSONB (encrypted)legacyCode, userCode, password, privateKey
jdIspbString8 digits (institution’s ISPB)
webhookUrlStringHTTPS URL for notifications
webhookSecretStringHMAC secret for validation
feeEnabledBooleanEnables fee charging
duplicateWindowSecIntegerDeduplication window (10-300, default 60)
tenantModeEnumDATABASE, SCHEMA, SINGLE

Entity relationships


OrganizationConfig (1) ──< has many >── (*) Transfer
                                           ├─< has many >─ (*) TransferStatusHistory
                                           └─< originates from >─ (0..1) PaymentInitiation

JDIncomingMessage (1) ──< creates >── (0..1) Transfer (of type TED_IN)
Data ownership: Each entity is owned by ONE component, following Hexagonal Architecture principles.

Indexes and performance


Main indexes

TableIndexPurpose
transfers(organization_id, created_at)Paginated listing by date
transfers(organization_id, status)Filter by status
transfers(control_number)Lookup by JD number
jd_incoming_message(sequence_number)At-least-once deduplication
transfer_status_history(transfer_id, changed_at)Chronological audit

Partitioning

Audit tables are partitioned by month for better performance in historical queries and to facilitate data retention management.

Reconciliation fields


FieldUsage
controlNumberJD SPB control number (unique per transfer)
transferIdLerian internal identifier
confirmationNumberUser-readable number
createdAtCreation timestamp
completedAtCompletion timestamp
Transfer history is kept for 5 years, per BACEN regulatory requirements.