Skip to content

E-Mandate Applet

Overview

An e-mandate is a customer’s standing authorisation, given through their own bank, for you to debit their account directly. In Malaysia that authorisation is granted over FPX (Financial Process Exchange), the national payment gateway, and BigLedger stores the resulting mandate against the customer entity it belongs to.

There is no installable E-Mandate applet. bl_applet_hdr holds no row — of any status — whose code, name or routerLink mentions a mandate or FPX (queried 2026-09-15). The e-mandate capability described on this page is backend-only: it is reachable through the …/paygw/my/fpx/… endpoints listed below and through whatever front end a tenant points at them. A front end exists in the repository (blg-applet-core-akaun-platform-e-mandate-applet); it is not registered, so it cannot be installed from the Applet Store, and the section “The e-mandate front end” below records what it does and does not do.

Where it fits

UpstreamThisDownstream
A settlement method of type FPX_EMANDATE, carrying the FPX seller credentials and signing certificate — settlement methods are documented on the Cashbook applet pageThe mandate record on the customer entityCollections taken against the mandate, settled through the Cashbook applet
A customer entity in Customer Maintenance — the mandate hangs off its entity line

Customer Maintenance already lists FPX e-mandate among the settlement methods a customer can be given; this page is the reference for what that record actually is.

Screens and menus

There is no installed screen surface for a mandate. Every capability on this page is reached through the …/paygw/my/fpx/… endpoints, and the one place a mandate becomes visible to a normal user is the customer’s own record in Customer Maintenance, where FPX e-mandate appears among the customer’s settlement methods. The screens described below exist only in an unregistered repository build and cannot be installed.

The e-mandate front end

A repository named blg-applet-core-akaun-platform-e-mandate-applet builds an Angular applet under the route eMandate, with a sidebar of E-Mandate Create · E-Mandate Update · E-Mandate Terminate plus Settings and Personalization. It has no registry row, so it cannot be installed. It is documented here because the screenshots and menu names circulating internally come from it, and because what it does is not what its labels say.

Read from the repository at commit 3bf0ec05b921:

  • Create is a real form — Online Direct Debit Enrolment, one Details tab, the fields Reference Number, Name, Email, Phone Number, ID Type, ID Number, Bank, Single / Multiple Signatory, Expiry Date, Extended Expiry Date, Max Amount per DD Transaction, Frequency, Initial Collection Option, Initial Collection Amount, Collection Date Start / End, Maximum Frequency, Purpose of Payment, Collection Amount.
  • Only the CREATE button is wired. Save & Email, Save As Draft and Cancel carry no click handler at all. Nothing in the applet sends an e-mail to anybody.
  • Update and Terminate are the same component, GenericContainerComponent, and it lists internal sales ordersInternalSalesOrderService, columns Doc No · Location · Customer Name · Created Date · Created By · Status, with the Status column bound to a stock-balance field that a sales order does not have. There is no mandate listing, no amend screen and no terminate screen.
  • The applet’s create action does not call the FPX endpoints described above. It posts the raw form to a payment-gateway init-form service, and the object it assembles for FPX — the one carrying the transaction GUID, the bank id and the frequency — is built and then discarded.

Treat the three menu items as unfinished work, not as a workflow. The capability that is real is the API.

Configuration

Everything that has to be right before a mandate can be created lives in another applet. The e-mandate front end in the repository has the two settings screens every Wavelet applet carries — Settings → Field Settings and Default Selection, plus Personalization — and neither of them is wired to anything: the toggles on the field-settings screen carry no form binding and its SAVE button has no click handler, and the routed default-selection component is never given the applet container it writes into, so its SAVE emits nothing. Nothing in the applet reads a setting key of any kind (checked across blg-applet-core-akaun-platform-e-mandate-applet @ 3bf0ec05b921). Since the applet has no registry row and cannot be installed, there is nowhere for a setting to be stored in the first place.

So there is one configuration surface that matters, and it is the settlement method.

Before you can

  • A settlement method whose reference is FPX_EMANDATE, carrying two extension rows — FPX_SELLER_ID and FPX_EXCHANGE_ID. A missing method fails with NO_FPX_STL_MTHD_FOUND; a missing extension with NO_FPX_STL_MTHD_DETAILS_FOUND.
  • A signing certificate on that settlement method. Upload it through POST /core2/tnt/dm/erp/settlement-methods/current-fpx-public-cert-upload/{hdrGuid}; the next certificate in a rollover goes to …/next-fpx-public-cert-upload/{hdrGuid}.
  • The buyer’s bank must exist in bl_fi_bank_hdr with country_code = MYS and a bank code that matches fpx_buyerBankId, or the request fails with Invalid buyer bank id. Fetch the live list from GET /core2/tnt/dm/paygw/my/fpx/banks.
  • A payment reference numberGET /core2/tnt/dm/paygw/my/fpx/pmt-ref-no increments the tenant’s SETTLEMENT-METHOD-FPX-EMANDATE sequence and returns the next value.

Permissions

Every authenticated FPX endpoint — the AD request and all three read endpoints — accepts the same set: the caller is a tenant OWNER or ADMIN, or holds one of API_TNT_DM_PGW_FPX_OWNER, API_TNT_DM_PGW_FPX_ADMIN or API_TNT_DM_PGW_FPX_CREATE.

API_TNT_DM_PGW_FPX_MEMBER is defined in TntPgwPermissions but is not accepted by any endpoint on this controller, so there is no read-only role for mandates: anyone who may look at a mandate may also raise one.

The two AC callbacks take no token at all.

Fields

There is no working create form, so “the fields” here means two different things: the rows a mandate is made of once it exists, and the fields the AD request must carry to create one. Both are below. The form in the unregistered front end asks for a third, longer set — reference number, signatory, initial collection option, collection dates — and discards most of it; see The e-mandate front end.

How a mandate is stored

A mandate is not a document. It has no header, no lines, no signum, and it posts nothing to the ledger. It is a set of rows on the customer’s master-entity record (EMandateContainer):

RowWhat it holds
bl_fi_mst_entity_lineThe mandate itself — one row per mandate, hanging off the customer entity
bl_fi_mst_entity_ext with param_code = PMT_MTHD_E_MANDATEThe FPX request message as JSON (buyer name, e-mail, bank, ID, IBAN-encoded terms, amount, product description), and the mandate’s status
bl_fi_mst_entity_ext with param_code = BL_FI_MST_ITEM_HDR_GUIDThe link to the FPX settlement method that supplies the seller credentials and the signing key
bl_fi_mst_entity_eventOne row per exchange with FPX — NEW_APPLICATION_AD_REQ, NEW_APPLICATION_DIRECT_AC, NEW_APPLICATION_INDIRECT_AC — each carrying the message sent or received

Because the terms live in the ext row’s JSON rather than in columns, there is no BigLedger-side validation of them beyond the checks listed under Creating a mandate.

What the request must carry

Every one of these is checked before anything is saved, and each throws its own message naming the field:

FieldMeaning
fpx_msgToken01 consumer, 02 or 03 business
fpx_sellerOrderNoYour reference for this mandate
fpx_txnAmountThe ceiling per collection. Must be greater than zero
fpx_buyerEmail, fpx_buyerName, fpx_buyerIdThe payer and their identity document number
fpx_buyerBankIdThe bank code from the FPX bank list
fpx_productDescWhat the collection is for
fpx_buyerIbanThe packed terms string — see below

fpx_buyerIban is unpacked into six values, four of which are validated: application type must be 01, 02 or 03; phone number must be present; maximum frequency must be present and greater than zero; frequency mode must be present (DL daily, WK weekly, MT monthly, YR yearly); effective date must be present. The expiry date is carried but not checked.

Three values are fixed by BigLedger and cannot be set per request: seller bank code 01, currency MYR, and FPX message version 7.0. A mandate in any other currency is not supported.

Lifecycle and effects

A mandate is not a document. It has no server document type, no quantity or amount signum, and no row in bl_fi_generic_doc_hdr, so none of the usual document machinery touches it: no journal line, no stock movement, no e-Invoice, no knock-off, no VOID. Its whole life is the two-step exchange below, and every step of that exchange happens inside the HTTP request that triggers it.

Nothing sweeps a pending mandate. There is no job processor for FPX or for mandates of any kind — JobProcessorClassName names none at backend commit 2ca2a4492afa — no queue, no retry and no scheduled reconciliation with FPX. A mandate whose confirmation never arrives stays at NEW_APPLICATION_PENDING_AUTHORIZATION for as long as nobody looks at it, and it will not appear on any report, because no report lists mandates.

The one thing that moves it is a read: GET …/fpx/e-mandate-event/{eventGuid} asks FPX for the current status and writes the answer back when the stored event is still ACTIVE or PENDING_AUTHORIZATION. Reconciling mandates is therefore something a person or an integration has to do on a schedule of its own — the platform will not do it for you.

The AD / AC exchange

Every change to a mandate — creating it, amending it, ending it — is the same two-step exchange with FPX. BigLedger builds and signs an AD (authorisation request) message; FPX replies with an AC (authorisation confirmation) message, either straight back to the server or through the customer’s browser.

  1. You post the mandate to POST /core2/tnt/dm/paygw/my/fpx/ad-request-message with an EMandateContainer body. BigLedger validates it, saves it if this is a new application, records an AD_REQ event, and returns the signed request message.

  2. The signed message is submitted to FPX, which takes the customer to their own bank to approve it.

  3. FPX confirms, by one of two routes:

    • POST /core2/tnt/dm/paygw/my/fpx/direct-ac/{tenantCode} — server to server. Returns JSON.
    • POST /core2/tnt/dm/paygw/my/fpx/indirect-ac/{tenantCode} — the customer’s browser is redirected here. Returns HTTP 302 to a status page.

    Both are anonymous endpoints — no login token. They are authenticated by the fpx_checkSum signature on the message, and a mismatch fails with CLIENT_FPX_CHECKSUM_VERIFICATION_FAILED.

  4. BigLedger updates the mandate from the confirmation: it stamps the AD event with the outcome, records the AC as a second event, and rewrites the mandate’s status or terms.

What the three application types do

The type is not a separate field — it is the first two characters of fpx_buyerIban, which is a packed string rather than a bank account number.

CodeTypeEffect on a successful confirmation
01New applicationThe mandate row is created before the AD request is sent, then its status is set to NEW_APPLICATION_<outcome>
02MaintenanceThe stored e-mail, amount and terms are overwritten from the request. The status is not changed — a maintained mandate keeps whatever status its new application left it with
03TerminationThe status is set to TERMINATION_<outcome>, but only if the outcome was not UNSUCCESSFUL

Maintenance and termination both require the mandate to already exist; if it does not, the request fails with EMANDATE_GUID_DOES_NOT_EXIST.

The outcome comes from one FPX field

fpx_debitAuthCode on the confirmation decides everything:

fpx_debitAuthCodeOutcome
00SUCCESSFUL
99PENDING_AUTHORIZATION
anything elseUNSUCCESSFUL

Creating a mandate

Creating, amending and terminating a mandate are the same exchange with a different application type in fpx_buyerIban, and all three are API calls — there is no working screen for any of them. Before the first one will succeed you need the settlement method and certificate under Before you can; the body has to carry the fields under What the request must carry.

For a new application (01) the mandate rows are written to the customer entity before the AD request is signed, so a customer whose bank later declines still has a mandate row — at NEW_APPLICATION_UNSUCCESSFUL. Nothing removes it. For maintenance (02) and termination (03) the mandate must already exist or the call fails with EMANDATE_GUID_DOES_NOT_EXIST.

Statuses

Two different status values are in play, and they are easy to confuse.

On the mandate (bl_fi_mst_entity_ext.status) — the application type and the outcome, joined with an underscore:

StatusWhat it means
ACTIVEThe row exists but no FPX exchange has completed against it
NEW_APPLICATION_PENDING_AUTHORIZATIONSent to the bank; the customer has not finished approving
NEW_APPLICATION_SUCCESSFULAuthorised. This is the state a mandate you can collect against is in
NEW_APPLICATION_UNSUCCESSFULThe bank or the customer declined
TERMINATION_PENDING_AUTHORIZATIONTermination sent, not yet confirmed
TERMINATION_SUCCESSFULEnded

On each event (bl_fi_mst_entity_event.status) — ACTIVE, SUCCESSFUL, PENDING_AUTHORIZATION, NO_TRANSACTIONS_FOUND or UNSUCCESSFUL.

There is no expiry status and no rejection status. An expiry date is carried inside the packed fpx_buyerIban string and is enforced by the bank, not by a BigLedger status transition; a decline is …_UNSUCCESSFUL.

Reading a mandate can move it. GET …/fpx/e-mandate-event/{eventGuid} does not simply return what is stored: if the underlying AD event is still ACTIVE or PENDING_AUTHORIZATION, BigLedger asks FPX for the current status (an AE enquiry) and writes the answer back before replying. A read of a pending mandate is therefore also a refresh of it.

Related applets

A mandate is not a document, so there is no document before it and none after it. Two applets own the halves of it, and both are places you will have to visit before an AD request will succeed.

AppletWhy you end up there
Customer MaintenanceThe mandate is rows on a customer’s entity record, so every mandate starts as a customer created here. This is also the only screen in the product where the existence of a mandate shows: FPX e-mandate sits among the customer’s settlement methods, with nothing behind it explaining what was stored.
CashbookSettlement methods are documented on the Cashbook page, and the FPX_EMANDATE method is what carries the seller id, the exchange id and the signing certificate. Without it the AD request fails at the first check with NO_FPX_STL_MTHD_FOUND. Collections taken against a mandate also settle through the cashbook.

Nothing else reads a mandate. It posts no journal, touches no document, and no report in the product lists mandates — which is why the only way to see one today is to read the customer’s entity rows.

Troubleshooting

SymptomCauseFix
bl_fi_mst_entity_ext for PMT_MTHD_E_MANDATE not foundThe container was posted without the ext row that holds the FPX messageBuild the container with both ext rows — the mandate JSON and the settlement-method link
bl_fi_mst_entity_ext for BL_FI_MST_ITEM_HDR_GUID not foundThe mandate is not linked to a settlement methodAdd the link ext row before requesting the AD message
NO_FPX_STL_MTHD_FOUND / NO_FPX_STL_MTHD_DETAILS_FOUNDThe linked settlement method is missing, or has no FPX_SELLER_ID / FPX_EXCHANGE_IDCreate the FPX_EMANDATE settlement method and fill both extension values
Invalid buyer bank idfpx_buyerBankId does not match a Malaysian bank rowTake the code from GET …/fpx/banks, not from the customer
CLIENT_FPX_CHECKSUM_VERIFICATION_FAILED on a callbackThe certificate used to sign does not match the one FPX verified againstCheck which certificate the settlement method is serving — current or next
EMANDATE_GUID_DOES_NOT_EXIST on an amend or terminateApplication type 02 or 03 sent for a mandate that was never createdCreate the mandate with type 01 first
A mandate sits at NEW_APPLICATION_PENDING_AUTHORIZATIONThe customer has not finished approving at their bank, or FPX has not confirmedRead the event — the read triggers an enquiry to FPX and writes back the current answer

Related documentation

Last updated on