Skip to content

Changelog

This page records changes that affect a Partner Gateway integration. The endpoint reference remains the source for the current request and response shape.

2026-10-14 — Times are exact UTC instants

Section titled “2026-10-14 — Times are exact UTC instants”

No field or shape changes; some values are now correct.

  • Creation times. Before this date, created_at on payments and payouts (create, list and detail) and other times Moria’s database stamped itself were returned seven hours later than the real moment: the WIB clock reading carried a Z. They are now the real instant in UTC. If your integration subtracted seven hours, or treated these values as WIB, remove that. Values Moria set itself, such as expires_at and finalized_at, and webhook occurred_at / sent_at, were already correct.
  • Period filters. On GET /v1/partners/payments, /payouts and /member-transfers, a bare YYYY-MM-DD in from / to covers that whole day in WIB (Asia/Jakarta, UTC+7), as before. A full date-time is now taken as exactly the instant it names; before, it was read seven hours off. Send it with its offset, e.g. 2026-10-12T00:00:00+07:00.

2026-10-12 — Member transfers, the deposit, and a second factor in the console

Section titled “2026-10-12 — Member transfers, the deposit, and a second factor in the console”

Additive for the API; one change for everyone who signs in to the console.

  • Member transfers. POST /v1/partners/groups/{external_group_id}/members/{external_id}/transfers moves part of your balance into a wallet of a member you provisioned, with no fee: the payment wallet (wallet: "open_loop", the default) or the member’s main balance in your organisation ("closed_loop"). Off until Moria enables it for your account; needs the transfer-to-member permission, issued by Moria. Read with GET /v1/partners/member-transfers and GET /v1/partners/member-transfers/{id}. See Member transfers and the deposit.
  • Deposit. Owners can set part of the released balance aside in the console to cover member transfers while payments settle. It is never paid out to a bank.
  • Balance. GET /v1/partners/balance adds reserve, advance_used and transferable_to_members. Without a deposit the first two are zero and nothing else changes.
  • Webhooks. New events member.transfer.succeeded and member.transfer.failed. Ignore event types you do not know, as before.
  • Idempotency. A transfer’s key covers the amount, the member and the wallet. Leaving wallet out and sending "open_loop" are the same request; reusing the key with a different wallet is refused with REQUEST_IDEMPOTENCY_KEY_REUSED.
  • Errors. New codes FUNDS_TRANSFER_SUSPENDED and STATE_MEMBER_WALLET_NOT_READY. FUNDS_SETTLEMENT_PENDING, which payouts already returned when money was not released yet, is now documented and applies to member transfers too.

Added documentation for GET /v1/partners/payment-instructions?lang=id|en: bank/wallet channel codes and ordered customer steps. Initial coverage is 12 VA banks with general transfer guidance and DANA checkout. OVO and ShopeePay remain pending verification. API-key authentication and read-gateway apply; no HMAC is needed. See Payment instructions.

2026-09-17 — Read requests use the API key only

Section titled “2026-09-17 — Read requests use the API key only”

Partner Gateway read-only GET requests no longer require an x-partner-signature. Send Authorization: Bearer <api_key> and Moria checks the read-gateway permission. There is no request body, signature string, or timestamp to construct for these reads.

The POST payment, quote, and payout endpoints still require the HMAC signature over the exact raw request body. See Authentication for the two request types.

The 2026-09-16 Partner Gateway contract baseline established the contract before the first partner integration. Treat clients built against the previous contract as requiring migration.

The Partner Gateway tells the pricing engine that the partner’s amount is what the payer pays. Fees come out of that amount:

FigureMeaning under DEDUCTED
amount / grossWhat the payer pays and what leaves the partner’s balance for a payout
feeThe combined provider fee and Moria fee shown to the partner
net_amountWhat the partner receives after the fee

For example, a collection can be represented as:

amount / gross = 11200.0000
fee = 78.4000
net_amount = 11121.6000

DEDUCTED is a default, not a request field. A partner- or organisation-scoped pricing rule may explicitly use ON_TOP:

ModePayer paysRecipient receives
DEDUCTEDbase_amountbase_amount - provider_fee - margin
ON_TOPbase_amount + provider_fee + marginbase_amount

ON_TOP remains the meaning used by Moria’s own member/product paths: the member states what should land, and the fees are added above it. A negotiated Partner Gateway rule can use the same mode without changing the API code.

Partner-facing surfaces expose one fee figure. The provider/margin split remains internal for accounting and reconciliation, but it is not part of the Partner Gateway contract.

SurfacePrevious contractCurrent contract
Payment responses and quotesprovider_fee + marginOne combined fee
Payout responses and payout.succeededamount onlyamount + fee + net_amount
GET /v1/partners/balancewithdrawablebalance + available + pending

Under the default DEDUCTED payout mode, amount is reserved and leaves the partner balance; fee is deducted from it; net_amount is what reaches the bank. The three balance figures answer different questions: total partner liability, currently withdrawable funds, and funds still pending settlement.

See Create a payment, Request a payout, and Check your balance for the current examples.

2026-09-16 — Whole-IDR provider validation

Section titled “2026-09-16 — Whole-IDR provider validation”

The provider boundary for money-in instruments requires gross to represent a whole IDR amount. Moria checks the canonical DECIMAL(20,4) value exactly in integer units; it does not use floating-point arithmetic and it does not round.

Under the default DEDUCTED mode, this means the payer’s requested amount must be whole IDR. Under ON_TOP, the resulting provider gross—including fees—must be whole IDR.

Input grossResult
11200.0000Allowed; sent to the provider as 11200
12084.0000Allowed
11200.4000Rejected before the provider call
10120.3500Rejected before the provider call
0.0001Rejected before the provider call
0.0000Not rejected by this whole-IDR check; existing amount/domain validation still applies

Fractional provider amounts return the existing invalid-payload contract:

{
"error": {
"code": "REQUEST_INVALID_PAYLOAD",
"message": "Payment amount must be a whole IDR amount for this payment method."
},
"request_id": "req_…"
}

This validation does not change DEDUCTED or ON_TOP pricing, internal gross_amount, net_amount, provider fees, margins, database columns, or accounting records. In particular, fractional internal fees and net amounts remain valid when the provider-facing gross is whole. No amount is rounded up or down.

For the complete failure taxonomy, see Errors.