Master RFC for Outbound Flow
Reference Documents
| Reference | Document Location |
|---|---|
| OPS | Outgoing Payment Service RFC |
| PRD | ISO Migration - Outbound MVP |
| PRD2 | ISO Migration - Inbound MVP |
| DIAG | Diagrams .drawio |
| FXS | SWIFT in FXSuite |
| SWIFTGW | SWIFT Gateway RFC |
| INBOUND | Inbound MVP RFC |
Problem Description
ISO 20022 is an ISO standard for data exchange between financial institutions that is being implemented in various financial market agents and clients that we use today. Today our database, our systems and our processes are based on SWIFT MT messages and we must be migrated to the new SWIFT ISO 20022 CBPR+ format, also known as MX format. It has significant changes in the message format including field formats and new structured information fields, it changes the message file format we send to SWIFT and instead of one message type we exchange with banks we have different messages types depending on the bank.
Background
At the moment SWIFT payments are processed using FXSuite, SWIFT Service, Transformer, Autoclient Balancer, and Autoclient. More detailed information can be found in the linked FXS document. Responsibilities of the services:
- PSSDS - Holds scheme routing configuration to where each payment can be sent to.
- the-BAVS - Validates if the beneficiary account number supports the scheme.
- FXSuite - Routes payments, chooses source account, calls the appropriate scheme service, and produces Bank Account Entries for BOS. Also receives incoming files directly from Autoclient SFTP.
- Transformer - Converts messages from JSON to MT format and back with different rules for banks, countries, and currencies.
- SWIFT Service - Ensures idempotency, translates messages, and forwards to Autoclient Balancer.
- Autoclient Balancer - distributes messages between available Autoclient SFTP servers.
- Autoclient SFTP - SFTP server running Autoclient that sends and receives files over the SWIFT network.

Business domain
FXSuite is being deprecated and the outbound flow is replaced by the Outgoing Payment Service. Inside the OPS a payment is a credit transfer initiated by BOS. Payment has all Anti-Money Laundering checks performed before the payment is sent to the OPS. Money movement and creating ledger entries is also outside of the Outgoing Payment Service. The Outgoing Payment Service takes care of payment execution through many schemes and it has 3 main message flows.
- We send payment as the scheme-specific credit transfer message and receive status updates for it.
- We get immediate ACK/NACK as either an HTTP status code or a file depending on the connection to the Scheme
- ACKed payments then can be accepted or rejected.

- The receiver of the accepted payment (credit transfer) may decide to cancel it. This is a return and we notify BOS that we received a scheme-specific return message.
- The receiver can also reject payment in #1

- BOS may ask to cancel the accepted payment. This is a recall and if the scheme supports it, we send it out in a scheme-specific message. If the receiver agrees to return the money, we receive a return like in #2. Recall may be rejected as well.

This is currently implemented for SEPA Core.
Solution
In the scope of Outbound MVP, SWIFT is just another scheme service connected to the Outgoing Payment Service. The Outgoing Payment Service has the interface to the Scheme service already defined and implemented in SEPA Core.

A new Source Account Selection service will be implemented and used by the Outgoing Payment Service to replace the FXSuite account selection.
Two new services will implement the SWIFT Scheme:
- SWIFT Gateway
- SWIFT Adapter
Deviations from the "standard" Outgoing Payment Service flow
- We do not participate in the SWIFT network. Whatever messages Bank and Ebury exchanges depend on the agreement with Banks:
- Payment is initiated with either pacs.008 or pain.001 messages
- For recalls camt.056 is used to recall pacs.008 and camt.055 is used to recall pain.001 messages
- Debit/Credit notifications are received with either camt.054 or camt.052 messages
- We may or may not receive positive confirmations of payments (pacs.002) directly. Therefore Bank Account Entries are created in inbound flow based on camt.054/camt.052 Debit notifications.
- We may or may not receive returns (pacs.004) directly. Therefore Bank Account Entries are created in inbound flow based on camt.054/camt.052 Credit notifications.
Source Account Selection
The goal is to choose from which Ebury account funds will be sent to the beneficiary. The current source account selection code in FXSuite chooses the account based on - scheme (SWIFT, FPS, ...) - payment currency - beneficiary account country
There are some hard-coded exceptions for payment currency, beneficiary account country and Ebury entity.
To further improve existing routing algorithm and reduce the need for manual payment execution, we will need to update BOS to include the source bank of Liquidity Provider for payments and some additional information for independent payments.
This service will have its own RFC with more detailed information.
SWIFT Gateway
SWIFT Gateway will implement the technical protocol of sending ISO messages to SWIFT. At the moment it will use the existing Autoclient SFTP protocol but it might be switched to the Autoclient Cloud API without requiring changes to the SWIFT Adapter. It is replacing the existing Autoclient Balancer and has it's own RFC
Backups of actual files exchanged will be stored in S3 by SWIFT Gateway. The service sends and receives Protocol Data Units containing the ISO XML messages.
Inputs through Kafka topics:
- ISO XML message to be sent to SWIFT
Outputs through Kafka topics:
- ISO XML message received from SWIFT
- Acknowledgement or Negative Acknowledgement of message previously sent to SWIFT (ISO XML with additional fields)
- Error message of message previously sent to SWIFT consisting of error code, text and the filename of original message. Potentially it will contain the identifiers of ISO XML message sent, but that is within the scope of SWIFT Gateway RFC.
SWIFT Adapter
SWIFT Adapter will implement the business logic for the SWIFT scheme. It will have functionality both for inbound flow (another RFC) and outbound flow (this RFC).
For the outbound flow, it will receive payment and recall requests from the Outgoing Payment Service through Kafka topics. Those requests will be translated to the ISO XML message format and sent to SWIFT Gateway. Messages received from SWIFT through SWIFT Gateway will be converted to the format expected by the Outgoing Payment Service and sent to it through Kafka topics.
A third-party tool Transformer was used to translate FIN messages. It was producing different message content based on the bank, beneficiary country, and currency.
For ISO XML messages we will implement the translation by defining models of the Outgoing Payment Service and ISO XML messages and writing Python code to map the fields. Libraries like Pydantic and xsdata may be helpful. We will not only have different message content but different message types for banks as well. We want to be able to fully implement and test business requirements within the service like:
When currency is one of MAD, BGN, DKK, RON, SEK, CAD, NOK, CZK, HUF, PLN, AUD for all client entities and beneficiary bank country United Arab Emirates and sender BIC EBURGB2L and receiver BIC CITIGB2LCTI and all source accounts the remittance information field in pacs.008 must start with "/REF/INS/EBURGB2L".
Manual payments
Manually executed payments start in BOS by creating MT103 and SIF files from Pre-execution page. Those files are then manually updated with the correct information and sent manually from tools provided by banks. The message transformation is done by HTTP endpoint in FXSuite.
For ISO messages we must have a similar functionality. BOS will call "SWIFT Adapter" directly to create the XML message and allow user to download it. There are two options for that:
- Creating a new Kafka topic and consumer that works like the existing consumer except it will not send the XML message to SWIFT Gateway. The response will be published to another topic and consumed by BOS
- Creating a HTTP endpoint in SWIFT Adapter that will be called by BOS
SWIFT Payment - Happy Flow

- BOS Sends payment to OPS through ebury.events.payments.pre-execution-check-completed.v1 Kafka topic
- OPS decided to send payment through SWIFT and sends it to SWIFT Adapter
- OPS publishes payment status update about the route chosen
- OPS publishes notifcation when Payment is forwarded to the Scheme service
- SWIFT Adapter converts the JSON message to either pacs.008 or pain.001 message and fills fields according to configuration for bank, currency, and country rules
- SWIFT Adapter sends the XML message to SWIFT Gateway where it is put inside InterAct file, signed and sent to SWIFT
- SWIFT Adapter notifies OPS that the payment has been sent to the Scheme
- OPS will publish the update for BOS that Payment has been forwarded to the Scheme
- SWIFT Adapter will receive information about Acknowledgement
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Payment has been sent to the Scheme
Once payment is accepted the following steps will happen in the inbound flow (a different RFC: Inbound RFC)
- SWIFT Adapter will receive a Debit notification in camt.054 or camt.052 message
- SWIFT Adapter will publish the Debit notification event for other services
- Incomming Connector will create BOS Bank Account Entries from that
- OPS will receive Debit notifications from Incomming Connector topic
- OPS will publish the update for BOS that Payment is completed
SWIFT Payment - Rejection

- BOS Sends payment to OPS through ebury.events.payments.pre-execution-check-completed.v1 Kafka topic
- OPS decided to send payment through SWIFT and sends it to SWIFT Adapter
- OPS publishes payment status update about the route chosen
- OPS publishes notifcation when Payment is forwarded to the Scheme service
- SWIFT Adapter converts the JSON message to either pacs.008 or pain.001 message and fills fields according to configuration for bank, currency, and country rules
- SWIFT Adapter sends the XML message to SWIFT Gateway where it is put inside InterAct file, signed and sent to SWIFT
- SWIFT Adapter notifies OPS that the payment has been sent to the Scheme
- OPS will publish the update for BOS that Payment has been forwarded to the Scheme
- SWIFT Adapter will receive information about Acknowledgement
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Payment has been sent to the Scheme
- SWIFT Adapter will receive a negative status in pacs.002 message
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Payment has been rejected by Scheme and notify Customer Payments (Outbound) Tream
In case of a NACK:
- SWIFT Adapter will receive information about Negative Acknowledgement
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Payment has not been sent to Scheme and notify Support and Customer Payments (Outbound) Treams
SWIFT Payment - Recall

- BOS will send a Payment Recall through a new Kafka topic (created in SEPA SCT Project)
- OPS will check if payment status allows it to be recalled, it will enrich the recall request with the original payment information, and find the Scheme/Route of the original payment
- For SWIFT payments, OPS will send the Recall to SWIFT Adapter
- OPS publishes notifcation when Recall is forwarded to the Scheme service
- SWIFT Adapter converts the JSON message to camt.056 and sends the XML message to SWIFT Gateway where it is put inside InterAct file, signed and sent to SWIFT
- SWIFT Adapter notifies OPS that the Recall has been sent to the Scheme
- OPS will publish the update for BOS that Recall has been forwarded to the Scheme
- SWIFT Adapter will receive information about Acknowledgement
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Recall has been sent to the Scheme
- SWIFT Adapter will receive a status update in camt.029 message
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Recall is pending and passed to next agent
- SWIFT Adapter will receive a status update in camt.029 message
- SWIFT Adapter will publish status to OPS
- OPS will publish the update for BOS that Recall is accepted and payment is cancelled, and notify Customer Payments (Outbound) Tream
Funds will be returned through Return flow.
SWIFT Payment - Return

It starts with inbound flow (a different RFC: Inbound RFC)
- SWIFT Adapter will receive a Credit notification in camt.054 or camt.052 message
- SWIFT Adapter will publish the Credit notification event
- Incoming Connector will create BOS Bank Account Entries
- OPS will consume Credit notifications from Incomming Connector topic
- OPS will publish the update for BOS that Payment Return has been received and notify Customer Payments (Outbound) Treams
Service Ownership
| New Service | Service Name | Service Owner |
|---|---|---|
| Yes | Source Account Selection | PAY Team |
| Yes | SWIFT Adapter and/or Financial Adapter | Moneyflows: COP and PAY Teams |
| Yes | SWIFT Gateway | COP Team |
Alternatives
Use of Transformer
Transformer is used as the tool to translate between JSON and MT (FIN) messages. Transformer supports the MX (ISO XML) formats as well.
For the new ISO XML messages we decided to not use the Transformer because:
- It is a third-party software.
- All translations have to be defined through GUI which developers do not like and it's an extra tool to be learned.
- For most translations code has to be written using the Transformers graphical programming language which does not have any syntax checks and fails with unclear errors during runtime.
Use of Autoclient Balancer
We already have an Autoclient Balancer that works with SQS queues and hides the underlying SFTP protocol. However, it does not have existing functionality to receive the messages - it is done by FXSuite directly. File extensions (.fin) were hardcoded.
The decision was made to create a new service that:
- Works with Kafka instead of SQS
- Supports both directions: send and receive
- Supports the new InterAct file extensions (.ia)
Use of SWIFT Service
We already have a scheme service for SWIFT. However it works with SQS and there is almost no functionaly except calling Transformer and forwarding messages. Even if we keep the same service, everything would have to be developed from scratch for the outbound flow. There was also a risk of breaking or interrupting the execution of SWIFT Service while introducing so much new functionality.
The decision was made to create a new service ("SWIFT Adapter").
Caveats
We have service ownership per team and SWIFT Adapter will have functionality and inbound / outbound flows implemented by two teams. We might need to physically split the service for each team.
There is a similar situation with two teams relying on SWIFT Gateway. However, it does not have functional differences for inbound and outbound flow: both flows send and receive messages. COP team has started the implementation already and we expect it will be done by the time PAY team starts working on the outbound flow.
Operation
FXSuite was used by Operations to review payment status and content of MT messages sent and received, ACKs/NACKs received. FXSuite will no longer be involved therefor we will have to come up with a way to provide visibility of what happened with the payment. To be discussed:
- Providing an API and a Swagger UI
- Operations Portal UI
- Maybe: a Python shell for incident investigation
Another important feature is tools for working with Kafka topics: removing messages from Dead Letter Topic, moving messages from retry topics to DLT, etc.
Security Impact
Since we’re ingesting new files from a 3rd party (SWIFT), the security team will be involved in the Swift Gateway RFC in order to discuss non-functional requirements to protect Ebury regarding the ingestion of these new files.
Performance Impact
According to Kibana logs we are processing around 2,500 outgoing SWIFT payments per day and 13,500 payments per week with no messages over the weekends. There are spikes of around 70 payments per minute and 3 payments per second.
The new ISO 20022 outbound flow should be capable of processing at least 5 payments per second to keep the same performance level.
Developer Impact
n/a
Data Contracts
The services will consume and produce messages in the format defined by the Outgoing Payment Service.
We will extend payment initiation messages from BOS with the information needed for ISO in a backward-compatible way:
- Structured Beneficiary address required for constructing MX message
- Additional information for source account selection
Data Sources
- BOS payment and beneficiary information received through ebury.events.payments.pre-execution-check-completed.v1 topic for outbound payments, recall requests
- SWIFT network
Deployment
Services will be deployed in Kubernetes following the standard steps described in Developers Handbook.
Dependencies
PAY and COP teams will be both working on the shared SWIFT Adapter service and there are few messages shared between both flows:
- Status report pacs.002 will be received for both flows. It contains original message name which uniquely identifies to which flow this pacs.002 belongs
- Some of Credit/Debit notifications processed in Inbound flow are needed to update status for Outbound flow.
Based on RFC Template Version 1.1