Skip to content

BOCHK (Bank of China Hong Kong)

About This Page

What: BOCHK's B2E deposit collection, FTS/FPS withdrawal remittance, matching rules, and scheduled tasks complete business rules, plus channel-side interface field details and moomoo-side adaptation mapping Audience: PMs needing in-depth understanding of BOCHK integration details Prerequisites: Bank Capability MatrixReading time: 12 minutes Owner: Deposit Product Manager

Key takeaway: BOCHK is the largest deposit source bank, collecting statements via B2E batch files — file pull frequency and parsing logic directly determine BOCHK users' deposit waiting time.


Capability Overview

CapabilitySupportedProtocol/ChannelCore Service
Deposit Statement CollectionB2E (Bank-to-Enterprise) XML APIbochk_flow_go (Go)
Withdrawal RemittanceFTS file channel (S14/S16)bochk_fts_mgr (Python)
Withdrawal FPSFPS (via BOCHK FPS channel)boc_fps method
Withdrawal Same-bank TransferFTS same-bankboc method
Withdrawal Cross-border WireWire transfertele_transfer method
eDDA/eDDI
BST

BOCHK is the largest source bank for deposit statements — most Hong Kong users deposit via BOCHK transfers, with the system collecting statements via B2E API and matching them to deposit applications.


Channel Interface Overview

DimensionDescription
Protocol TypeHTTP/HTTPS + XML (B2E Bank-Enterprise Direct)
AuthenticationDigital certificate + UserId/Password + ECertName/ECertPwd triple authentication
Data FormatXML (UTF-8 encoding), requests/responses use BOCHKE2B as root node
Collection ModeActive pull (3 daily scheduled + every 2 hours Flow Converter conversion)
Certificate Rotation900-day cycle, must renew 30 days in advance
Connection Timeout30 seconds
Rate LimitingBank-side rate limit returns RJ0002, does not trigger failover
Deduplicationacct_no + seq_no + currency + boc_date unique key, UPSERT operation

Comparison with Other Banks

BOCHK is the only bank using XML protocol — HSBC/Hang Seng use SFTP files, SCB uses HTTPS JSON, CGB uses FPS notification push. B2E XML features fixed structure and clear fields, but debugging requires attention to XML namespaces and encoding issues.


Deposit: B2E Statement Collection

What is B2E

B2E (Bank-to-Enterprise) is BOCHK's standard API interface for enterprise customers. moomoo queries company receiving account transaction statements via the B2E interface, then matches them with user deposit applications.

Receiving Accounts

moomoo has 5 currency receiving accounts at BOCHK; each user transfer goes into the corresponding currency account:

CurrencyAccount NumberConfig Key
HKD01267600088450HKCUR
USD01267608014549USCUR
CNY01267606013676CNCUR
JPY01287521127472JPCUR
SGD01287526723084SGCUR
Configuration Location

bochk_flow_go/conf/conf.toml[conf.futu_account.account_numbers]

B2E Three Query Interfaces

The system collects statements through three B2E interfaces at different times to ensure no missed records:

InterfaceScheduleWhat It QueriesTarget Table
TodayActivityDaily 06:00Current day real-time transactionsacct_trd_record
AcctStatementDaily 07:00Previous day complete statementacct_trd_record (is_addendum marked)
AcctActivityDaily 08:00Detailed account activity (with balance)boc_transaction_record

Additionally, a Flow Converter runs every 2 hours, converting raw records to the unified boc_bank_flow format for the matching engine.

Data Flow

B2E Protocol Key Points

  • Transport: HTTP POST, XML request/response body
  • Authentication: Token authentication (Ecert Name: FUTU1), Token 900-day rotation cycle
  • Timeout: 30 seconds
  • Deduplication: Based on acct_no + seq_no + currency + boc_date unique key, UPSERT operation
  • Error Handling:
    • E11071 / GE11012: No data (normal, not failure)
    • RJ0002: Request rate limit (does not trigger failover)
    • Other errors: Log and retry next time

Channel-Side Interface Details

Below are the complete request/response field definitions for the three B2E interfaces. All interfaces share the same authentication header (Head); differences are in request body and response fields.

Common Request Header (BOCHKE2B > Head)

Each B2E request has XML root node BOCHKE2B, with the Head section carrying authentication and routing information:

FieldTypeRequiredDescription
PackageIdstring(17)Package ID, auto-generated 17-digit number, unique per request. e.g. "12345678901234567"
CBSAcctNostringCBS account number (enterprise master account). e.g. "01227468128899"
UserIdstringUser ID. e.g. "FUTU1"
PasswordstringPassword (encrypted in transit)
ECertNamestringDigital certificate name. e.g. "FUTU1"
ECertPwdstringDigital certificate password (encrypted in transit)

Authentication Security

Password and ECertPwd are encrypted before transmission; certificate files are stored in protected server directories. Do not log plaintext values of these two fields.

Common Response Header

All B2E interface responses contain these header fields for determining request success:

FieldTypeDescriptionExample
TxStatusstringTransaction status, "S" = Success, "F" = Failure"S"
ErrorCodestringError code (empty on success)"E11071"
ErrorDescstringError description (empty on success)"No Record Found"
TxRefNostringBank transaction reference number"BOCHK20260429001"
TxDatestringTransaction date (YYYYMMDD)"20260429"
TxTimestringTransaction time (HHMMSS)"100530"

Interface 1: TodayActivity (Same-day Transaction Query)

Schedule: ~06:00 (first daily pull of current day real-time transactions)

Purpose: Query all transactions occurring today for a specified account. This is the earliest interface to get current day statements, used to match deposit applications as quickly as possible.

Request Parameters (TodayActivityREQ)

FieldTypeRequiredDescription
AcctNostringBank account number (i.e., receiving account number). e.g. "01267600088450"
Request XML Example
xml
<BOCHKE2B>
  <Head>
    <PackageId>12345678901234567</PackageId>
    <CBSAcctNo>01227468128899</CBSAcctNo>
    <UserId>FUTU1</UserId>
    <Password>***</Password>
    <ECertName>FUTU1</ECertName>
    <ECertPwd>***</ECertPwd>
  </Head>
  <TodayActivityREQ>
    <AcctNo>01267600088450</AcctNo>
  </TodayActivityREQ>
</BOCHKE2B>

Response Fields (Per Transaction Record)

FieldTypeDescriptionExample
SeqNostringSame-day transaction sequence, 6 digits left-padded. Format NN (numeric sequence)"000001"
CurstringCurrency code. Format 3-char ISO 4217"HKD" / "USD"
TimestringTransaction time (24-hour). Format HH:mm:ss"10:05:30"
TxRefNostringTransaction reference number (globally unique). Format 16 characters"1234567890123456"
AmountstringTransaction amount (2 decimal places). Format decimal(16,2)"100000.00"
ParticularsstringTransaction description/summary, used to identify transaction type. ≤200 characters"E-BANKING TRANSFER"
TxDetailstringTransaction type identifier. ≤50 characters"Transfer"
PayerOrPayeeNamestringPayer/payee name. ≤140 characters"CHAN TAI MAN"
PayerOrPayeeAcctNostringPayer/payee account number. ≤34 characters"01287500123456"

Field Notes

  • SeqNo: Increments within a day but resets across days. Deduplication must combine with date.
  • TxRefNo: 16-character globally unique transaction reference, the core field for matching and deduplication.
  • Particulars: The most critical business field — the system identifies FPS, online banking, CHATS and other transaction types by its prefix.
  • PayerOrPayeeName: Used for name matching; for deposits, this is the payer's name. Note case may be inconsistent.

Interface 2: AcctStatement (Account Statement Query)

Schedule: ~07:00 (queries previous business day's complete statement)

Purpose: Supplements TodayActivity by pulling the previous day's complete statement. Written to database with is_addendum marker, deduplicated and merged with current day real-time data.

Request Parameters (AcctStatementREQ)

FieldTypeRequiredDescription
AcctNostringBank account number. e.g. "01267600088450"
CurstringCurrency (HKD/USD/CNY/JPY/SGD). e.g. "HKD"
DatestringQuery date (YYYYMMDD), usually previous business day. e.g. "20260428"

Response Fields: Same structure as TodayActivity (SeqNo, Cur, Time, TxRefNo, Amount, Particulars, TxDetail, PayerOrPayeeName, PayerOrPayeeAcctNo).

Note

AcctStatement requires separate requests for each currency. The system iterates through the 5 receiving accounts' currencies, requesting HKD, USD, CNY, JPY, SGD statements separately. If a currency has no transactions, the interface returns E11071, which is normal.

Interface 3: AcctActivity (Account Activity Detail Query)

Schedule: ~08:00 (supports date range query, obtains most detailed account activity)

Purpose: This is the most field-rich interface, including balance information, GPI tracking, etc. beyond transaction details. Written to boc_transaction_record table, providing detailed data for reconciliation and audit.

Request Parameters (AcctActivityREQ)

FieldTypeRequiredDescription
AcctNostringBank account number. e.g. "01267600088450"
BicCodestringBIC code (filter specific bank). e.g. "BKCHHKHH"
RegionstringRegion code
StartDatestringStart date (YYYYMMDD). e.g. "20260428"
EndDatestringEnd date (YYYYMMDD). e.g. "20260429"
TransFlagstringTransaction direction filter: C = Credit (incoming), D = Debit (outgoing). e.g. "C"
TransCurstringFilter specific currency. e.g. "HKD"
MinAmtstringMinimum amount filter. e.g. "1000.00"
MaxAmtstringMaximum amount filter. e.g. "999999.99"
Optional Parameter Usage
  • TransFlag: During deposit collection, usually set to "C" (credit/incoming only), reducing irrelevant data. For reconciliation, omit this parameter to get all records.
  • MinAmt / MaxAmt: Used for large transaction monitoring scenarios; not used in routine collection.
  • BicCode: Used to filter transactions from specific source banks; not used in routine collection.

Response Fields (Per Transaction Record)

FieldTypeDescriptionExample
TransTypestringTransaction type identifier"Transfer"
TransRefstringUnique transaction reference. Format 16 characters"1234567890123456"
ParticularstringTransaction description/summary. ≤200 characters"FPS Transfer"
CurstringCurrency. Format 3 characters"HKD"
AmtstringTransaction amount. Format decimal(16,2)"50000.00"
TransFlagstringC = Credit (incoming), D = Debit (outgoing). Format 1 character"C"
PayerOrPayeeNamestringPayer/payee name. ≤140 characters"CHAN TAI MAN"
PayerOrPayeeAcctNostringPayer/payee account number. ≤34 characters"01287500123456"
TransDatestringTransaction date time (with timezone). Format YYYY/MM/DD HH:mm GMT+08:00"2026/04/29 10:05 GMT+08:00"
ValueDatestringValue date. Format YYYY/MM/DD"2026/04/29"
AcctNostringOwn account number"01267600088450"
LedBalstringLedger balance (after transaction). Format decimal(16,2)"5000000.00"
AvalBalstringAvailable balance (after transaction). Format decimal(16,2)"4800000.00"
GPIFlagstringSWIFT GPI indicator (has value for cross-border remittance)"Y"
GPIIdstringSWIFT GPI tracking ID"d2fca123-..."
ChequeNostringCheque number (has value for cheque transactions)"CHQ001234"

AcctActivity Unique Fields

Compared to TodayActivity and AcctStatement, AcctActivity has these additional key fields:

  • LedBal / AvalBal: Balance information, used for reconciliation and balance monitoring
  • GPIFlag / GPIId: SWIFT GPI tracking, for full-flow tracking of cross-border remittances
  • ChequeNo: Cheque number, needed for cheque deposit scenarios
  • ValueDate: Value date, may differ from transaction date (common in cross-border remittances)
  • TransFlag: Explicitly marks debit/credit direction; TodayActivity needs to determine this from amount sign

B2E Error Code Quick Reference

Error CodeMeaningHandling Strategy
E11071No data (No Record Found)Normal, don't retry — no transactions in that period
GE11012Alternate no-data markerEquivalent to E11071, don't retry
RJ0002Request rate limitWait then retry, do not trigger failover
E99999Generic system errorExponential backoff retry (30s → 60s → 120s)
E10001Authentication failureCheck if certificate/password expired
E10002Account unauthorizedContact bank to confirm B2E permissions

About RJ0002

RJ0002 is the bank-side rate limiting response; it should not trigger failover to a backup channel. The correct approach is to wait 30 seconds then retry. If RJ0002 occurs continuously, check whether multiple instances are pulling simultaneously.

B2E XML Field Mapping
XML FieldDatabase FieldDescription
SeqNoseq_noTransaction sequence
CurrencycurrencyCurrency
AmountamountAmount
BOCDateboc_dateTransaction date (YYYYMMDD)
BOCTimeboc_timeTransaction time
TxRefNotx_ref_noTransaction reference
ParticularsparticularsTransaction summary (used to identify transaction type)
PayerOrPayeeNamepayer_or_payee_namePayer/payee name
PayerOrPayeeAcctNopayer_or_payee_acct_noPayer/payee account

moomoo-Side Adaptation

B2E interface raw fields cannot be directly used by the matching engine — they must be standardized through Flow Converter and written to the boc_bank_flow table. Below is the complete field mapping and conversion logic.

Statement Standardization Mapping

B2E Raw FieldBankFlow Standard FieldConversion LogicDescription
TxRefNotransaction_id"BOC_" + YYYYMMDD + "_" + TxRefNoAdd prefix to prevent cross-bank ID conflicts
AmountcreditDirect mapping decimal(16,2)Deposit statements take credit amount
CurccyDirect mapping (HKD/USD/CNY/JPY/SGD)ISO 4217 three-character code
TimetimeHH:mm:ssHHMMSS (remove colons)Unified to 6-digit number format
ParticularsremarksDirect mappingPreserve original description for transaction type identification
PayerOrPayeeNameen_nameDirect mappingPayer English name
PayerOrPayeeAcctNocustomer_accountDirect mappingPayer bank account
TxDetailtypeTransaction type identifierUsed for classification statistics
BOCDateboc_dateYYYYMMDD → DATETransaction date
AcctNoacct_noDirect mappingPayee account (moomoo's account)
SeqNoseq_noDirect mappingTransaction sequence

transaction_id Generation Rule

transaction_id = "BOC_" + boc_date + "_" + tx_ref_no

Example: TxRefNo is 1234567890123456, date is 20260429, generates: BOC_20260429_1234567890123456

This ID is globally unique and is the core identifier for deduplication and matching.

Transaction Type Auto-Identification

The system automatically identifies transaction types through the statement's particulars (transaction summary) field. Different types have different matching rules and fee tolerances:

Particulars KeywordIdentified AsAuto-depositFee Characteristics
FPS TransferFPS Faster PaymentNo fees, exact match. Most common deposit method
E-BANKING TRANSFEROnline banking transferNo fees, exact match. BOCHK online banking arrival
CHATS TransferCHATS local clearingMay have fees, local tolerance. Instant payment settlement
REMIT INCross-border remittanceIntermediary bank fees, cross-border tolerance. Overseas inward, largest tolerance
CBS TRANSFERCBS internal transfer❌ Match onlySpecial handling. BOCHK system internal transfer, requires manual review
ATM TransferATM transferCannot verify source, record only
Cheque ClearingCheque depositCheque has dishonour risk, requires manual confirmation
InterestInterest incomeNot a deposit statement, auto-ignored
Corresponding Code

deposit/src/app/Business/Match/BocMatch.phpNewMatchRule() method, routes to different rules based on remarks field regex matching.

Matching Rules Detail (BocMatch)

FPS Faster Payment Rules

DimensionRule
Identificationparticulars starts with "FPS"
Amount MatchExact match (statement amount = CRM application amount)
Name MatchExact match → auto-deposit; similar match → manual confirmation
Date WindowApplication date ± 15 days
Auto-deposit✅ Auto-deposit when amount exact + name exact
Card Number CheckBOC card number must be 14 digits

Online Banking Transfer Rules

DimensionRule
Identificationparticulars starts with "E-BANKING TRANSFER"
Amount MatchExact match (no fee deduction)
Name MatchExact match → auto-deposit; similar match → manual confirmation
Date WindowApplication date ± 15 days
Auto-deposit✅ Auto-deposit when amount exact + name exact
Special HandlingOnline banking transfers usually include complete payer information, high match success rate

CHATS Local Clearing Rules

DimensionRule
Identificationparticulars starts with "CHATS"
HKD/CNH/JPY Amount ToleranceCRM - 20 ≤ Statement ≤ CRM
USD/SGD Amount ToleranceCRM - 3 ≤ Statement ≤ CRM
Name MatchExact match → auto-deposit; similar match → manual confirmation
Date WindowApplication date ± 15 days
Auto-deposit✅ Auto-deposit when within tolerance + name exact

Cross-border Remittance Rules (REMIT IN)

DimensionRule
Identificationparticulars starts with "REMIT IN"
HKD/CNH/JPY Amount ToleranceCRM - 420 ≤ Statement ≤ CRM
USD/SGD Amount ToleranceCRM - 60 ≤ Statement ≤ CRM
Name MatchExact match → auto-deposit; similar match → manual confirmation
Date WindowApplication date ± 15 days
Auto-deposit✅ Auto-deposit when within tolerance + name exact
NoteCross-border remittances passing through intermediary banks deduct 20-400 HKD in fees, hence tolerance is set to -420

CBS / ATM Rules

TypeIdentificationAuto-depositReason
CBS Internal Transferparticulars starts with "CBS TRANSFER"❌ Match onlyMay involve group internal fund transfers, need to distinguish customer deposits from operational transfers
ATM Transferparticulars starts with "ATM"Lacks payer information, cannot reliably verify source

Why is cross-border tolerance much larger? Cross-border remittances pass through intermediary banks that may deduct 20-400 HKD in fees; cross-border tolerance is set to -420, far larger than local's -20.

Why is the date window ±15 days? BOCHK is the largest deposit source; some users transfer then submit deposit applications much later (or vice versa); the 15-day window covers most delay scenarios.

Large Online Deposit Threshold

For online deposits triggered by bank card binding (bind_card, notice_type), there are also minimum amount limits:

  • HKD/CNH/JPY: Statement amount ≥ 10,000
  • USD/SGD: Statement amount ≥ 1,500

Deposit Timeout Configuration

Expected arrival times and timeout thresholds for different transfer methods, bank types, and currencies:

FPS Faster Payment

DimensionTime
Expected arrivalInstant (usually 1-5 minutes)
System timeout30 minutes
Timeout handlingMark for manual verification
Applicable currenciesHKD, CNY

Online Banking Transfer (BOCHK Same-bank)

DimensionTime
Expected arrivalInstant - 2 hours (depends on bank processing time)
System timeout4 hours
Timeout handlingMark for manual verification
Applicable currenciesHKD, USD, CNY, JPY, SGD

CHATS Local Clearing

DimensionTime
Expected arrivalSame day (processed during business day 09:00-17:30)
System timeoutT+1 business day
Timeout handlingMark for manual verification
Applicable currenciesHKD
NoteCHATS submitted outside business hours processed next business day

Cross-border Remittance (REMIT IN)

DimensionHKD/CNYUSDJPY/SGD
Expected arrivalT+1 - T+2T+1 - T+3T+2 - T+5
System timeoutT+3 business daysT+5 business daysT+7 business days
Timeout handlingMark for manual verificationMark for manual verificationMark for manual verification
NoteIntermediary bank processing time uncertainInvolves SWIFT clearingMinor currency clearing chains are longer

Scheduled Tasks

TaskFrequencyDescription
B2E TodayActivityDaily 06:00Pull current day statements
B2E AcctStatementDaily 07:00Pull previous day statement
B2E AcctActivityDaily 08:00Pull detailed account activity
Flow ConverterEvery 2 hoursConvert raw records to boc_bank_flow
match:bocEvery 3 minutesExecute BOC statement matching

Withdrawal: FTS File Channel

What is FTS

FTS (Fund Transfer Service) is BOCHK's batch remittance file channel. moomoo uploads withdrawal instructions to BOCHK's SFTP server in S14 format; BOCHK processes them and generates S16 result files for download.

Data Flow

S14/S16 File Formats

File TypeDirectionContent
S14moomoo → BOCHKWithdrawal instructions (payee info, amount, currency)
S16BOCHK → moomooProcessing results (transaction status, actual amount, balance)

S16 files are fixed-width format (1024+ characters per record), supporting multiple encodings (UTF-8, Big5HKSCS, GBK).

S16 File Key Fields
FieldDescription
seq_noTransaction sequence (16 digits, unique identifier)
futu_accountFutu regulatory account (14 digits)
t_dateTransaction date (YYYYMMDD)
v_dateValue date (YYYYMMDD)
ccyCurrency (HKD/USD/CNY...)
amountTransaction amount
borrowing_directionC=Credit (incoming) / D=Debit (outgoing)
ledger_balanceBalance after transaction
accountCounterparty account
nameCounterparty name
settlement_methodSettlement method
feeBank service fee
abstractTransaction summary

Relay Layer

bochk_relay is the B2E request relay layer (SRPC service), providing 5 RPC interfaces:

RPC MethodTimeoutPurpose
InternalTrans60sInternal transfer instruction
QueryInternalTrans30sQuery transfer status
QueryAcctBalance30sQuery account balance
QueryTodayActivity50sQuery today's activity
QueryAcctStatement50sQuery account statement

S14/S16 Consistency Check

The system compares key fields between S14 (instructions) and S16 (results) to ensure data consistency:

Monitoring MetricMeaning
1946146S14/S16 statement mismatch (needs attention)
1946147S16 has more complete information than S14 (normal)
1946148S14 and S16 completely consistent

Withdrawal: BOC FPS

Besides the FTS file channel, BOCHK also supports withdrawal via FPS (Faster Payment System) channel, with method code boc_fps.

Eligibility Conditions

ConditionRequirement
Receiving bank locationHong Kong
CurrencyHKD or CNY
Amount limit< 1 million
Bank card statusVerified (checked=1)
Excluded receiving banksICBC(10), Hang Seng(8), BOCHK(9), HSBC(11)

Why exclude these banks? These banks have their own dedicated withdrawal channels (e.g., Hang Seng uses hase online banking, HSBC uses hsbc online banking); using FPS might actually be slower or have limit restrictions.


Withdrawal: Same-bank Transfer & Cross-border Wire

ChannelMethod CodeApplicable Scenario
BOCHK Same-bank WithdrawalbocPayee is also a BOCHK account
BOCHK Cross-border Wiretele_transferCross-border remittance to overseas bank

Change Guide

If you need to modify BOCHK-related business rules, here are the specific modification locations:

Change RequirementModification LocationDescription
Add receiving currencybochk_flow_go/conf/conf.tomlAdd new currency account mapping
Modify deposit matching toleranceBocMatch.phplocalTransferSimilarAmount / isDifAreaSimilarAmountAdjust amount tolerance thresholds
Add transaction type identificationBocMatch.phpNewMatchRule()Add new particulars regex rules
Modify matching date windowBocMatch.phpdaySimilarAdjust day parameters
Modify FPS withdrawal limitBOCFPS.phpmake_able_whereModify amount threshold
Adjust FPS excluded banksBOCFPS.phpmake_able_whereModify bank_id exclusion list
Modify B2E pull frequencybochk_flow_go/conf/conf.toml → cron expressionsAdjust scheduled tasks
Modify matching frequencydeposit/doc/crontab.shmatch:bocAdjust cron interval
FTS timeout/retrybochk_relay various RPC method timeout parametersAdjust timeout durations
Add FTS monitoring metricsbochk_fts_mgrcus_fmonitor.pyAdd new monitoring IDs
Modify statement standardization mappingbochk_flow_go → Flow Converter moduleAdjust B2E → BankFlow field mapping
Modify deposit timeout thresholdsMatching engine configurationAdjust timeout duration per transfer method

Common Customer Complaints Top 3

#User FeedbackCauseCS Script
1"FPS deposit didn't arrive"particulars couldn't identify deposit method, statement marked unidentified"Your transfer is being processed, we will complete the matching as soon as possible"
2"Cross-border remittance had fees deducted"Intermediary/receiving bank fee deductions are normal"Cross-border remittances may incur bank service fees, actual credited amount is after bank deductions"
3"Deposit waited several days"BOCHK date window ±15 days, matching cycle is longer"BOCHK deposit matching cycle is longer, please wait patiently; contact customer service if it exceeds 3 business days"

After Reading

I want to...Go to
See BOCHK's position among all banksBank Capability Matrix
Understand the full matching engine logicMatching & Auto-Deposit
See withdrawal channel execution detailsChannel Execution Manual
Check B2E error codes and FTS status codesUnified Error Code Center
Look up TransType and Bank ID referenceDeposit Reference
Was this page helpful?

内部业务文档 · 仅限 moomoo 团队使用