TED IN allows your institution to receive transfers originated at other banks. The plugin automatically detects incoming transfers, validates the recipient, and credits the amount to the corresponding account.
How it works
Receiving a TED is an automatic process detected by the polling worker every 30 seconds.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Origin bank │────▶│ JD SPB │────▶│ TED Plugin │
│ sends TED │ │ (polling 30s) │ │ processes │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
┌─────────────────┐ │
│ Webhook │◀─────────────┤
│ (optional) │ │
└─────────────────┘ │
▼
┌─────────────────┐
│ Recipient │
│ account │
│ credited │
└─────────────────┘
Detection flow
- Every 30 seconds, the worker queries JD’s
RecebeMensagem service
- When finding a new
STR0008R2 message that doesn’t correspond to a transfer sent by the system, it’s identified as an incoming TED
- The raw XML message is immediately saved in the
JDIncomingMessage table (at-most-once guarantee)
Processing
- Creates a new
Transfer entity with type TED_IN and status RECEIVED
- Validates if the recipient’s account exists in CRM
- If the recipient is valid, calculates the cashin fee (if enabled)
- Credits the account in Midaz through
CreateCashinTransaction
- Updates status to
COMPLETED
- Sends webhook notification
Timeline
T+0: External bank sends TED
T+30s: Polling detects message (RecebeMensagem)
├─ Persist in JDIncomingMessage
└─ Status: RECEIVED
T+32s: Validate recipient in CRM
└─ Status: PROCESSING
T+35s: Credit account (Midaz CreateCashinTransaction)
└─ Status: COMPLETED
T+36s: Webhook notification sent
SLA: < 1 minute detection → < 5 seconds processing
TED IN states
RECEIVED → PROCESSING → COMPLETED
→ REJECTED (recipient not found)
| State | Description |
|---|
RECEIVED | Transfer detected, awaiting processing |
PROCESSING | Validating recipient and preparing credit |
COMPLETED | Amount credited to recipient’s account |
REJECTED | Recipient not found or invalid account |
Query received transfers
Endpoint: GET /v1/transfers?type=TED_IN
Query parameters
| Parameter | Type | Description |
|---|
type | String | Filter by type (TED_IN) |
status | String | Filter by status (COMPLETED, REJECTED) |
startDate | ISO8601 | Period start date |
endDate | ISO8601 | Period end date |
page | Integer | Page number (default: 1) |
pageSize | Integer | Items per page (default: 20, max: 100) |
Response
{
"transfers": [
{
"transferId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"type": "TED_IN",
"status": "COMPLETED",
"amount": 5000.00,
"feeAmount": 0.00,
"createdAt": "2026-01-21T10:15:00-03:00"
}
],
"pagination": {
"page": 1,
"pageSize": 20,
"totalItems": 150,
"totalPages": 8
}
}
Transfer details
Endpoint: GET /v1/transfers/{transferId}
Response
{
"transferId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"type": "TED_IN",
"status": "COMPLETED",
"sender": {
"ispb": "60746948",
"branch": "1234",
"account": "567890",
"name": "Carlos Oliveira",
"taxId": "98765432100"
},
"recipient": {
"accountId": "550e8400-e29b-41d4-a716-446655440000",
"name": "Empresa ABC Ltda",
"taxId": "12345678000199"
},
"amount": 5000.00,
"feeAmount": 0.00,
"netAmount": 5000.00,
"controlNumber": "JD20260121000042",
"createdAt": "2026-01-21T10:15:00-03:00",
"completedAt": "2026-01-21T10:15:05-03:00",
"statusHistory": [
{"status": "RECEIVED", "timestamp": "2026-01-21T10:15:00-03:00"},
{"status": "PROCESSING", "timestamp": "2026-01-21T10:15:02-03:00"},
{"status": "COMPLETED", "timestamp": "2026-01-21T10:15:05-03:00"}
]
}
Receiving fee (cashin)
The plugin can charge a fee on received transfers. Configuration is done per organization.
When enabled, the fee is calculated via plugin-fees and deducted from the credited amount:
netAmount = amount - feeAmount
Example with fee
{
"amount": 1000.00,
"feeAmount": 2.50,
"netAmount": 997.50
}
Recipient validation
The plugin validates the recipient using the document (CPF/CNPJ) provided in the STR0008R2 message:
- Queries CRM by document
- If found, identifies the corresponding account
- If not found, initiates chargeback
Rejected transfer
When the recipient is not found, a chargeback is automatically sent to the origin bank:
{
"transferId": "d4e5f6a7-b8c9-0123-defg-456789012345",
"type": "TED_IN",
"status": "REJECTED",
"amount": 3000.00,
"sender": {
"ispb": "60701190",
"branch": "0001",
"account": "123456",
"name": "Ana Costa"
},
"rejectionReason": "Recipient not found: document 11122233344 not registered",
"createdAt": "2026-01-21T11:00:00-03:00",
"rejectedAt": "2026-01-21T11:00:03-03:00"
}
Error handling
Critical errors and their actions:
- Recipient not found: Send chargeback to JD (STR0010R2), status=REJECTED
- Midaz unavailable: Retry 3x → DLQ (manual intervention)
- Duplicate: Unique constraint
sequenceNumber prevents duplicate credits
Receiving webhook
Configure a webhook to be notified in real-time about received transfers.
Event: transfer.incoming
{
"event": "transfer.incoming",
"timestamp": "2026-01-21T10:15:05-03:00",
"data": {
"transferId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"type": "TED_IN",
"status": "COMPLETED",
"amount": 5000.00,
"feeAmount": 0.00,
"netAmount": 5000.00,
"sender": {
"ispb": "60746948",
"name": "Carlos Oliveira"
},
"recipient": {
"accountId": "550e8400-e29b-41d4-a716-446655440000",
"name": "Empresa ABC Ltda"
}
}
}
See more details in Webhooks.
Reconciliation
For accounting reconciliation, use the following fields:
| Field | Usage |
|---|
controlNumber | JD SPB control number (unique per transfer) |
transferId | Lerian internal identifier |
createdAt | Detection timestamp |
completedAt | Credit timestamp |
Transfer history is kept for 5 years, as per BACEN regulatory requirements.
Processing guarantees
The plugin implements guarantees to avoid duplicates and losses:
| Guarantee | Implementation |
|---|
| At-most-once | Messages persisted BEFORE processing |
| Idempotency | Same sequenceNumber is not processed twice |
| Retry | Transient failures retried with exponential backoff |
| DLQ | Permanent failures go to dead-letter queue |
CRITICAL: The message is persisted in the JDIncomingMessage table BEFORE processing, ensuring no transfer is lost in case of failure.